Как получить совпадения имен файлов в директории, содержащей 1 миллион файлов

Вопрос или проблема

Как получить совпадения имен файлов в директории, содержащей 1 миллион файлов

glob Это медленно
File::glob(‘*’)

$files = File::allFiles($path);

$mages=array();
foreach ($files as $file)
{
    
    if ($file->getExtension()==='jpg' or $file->getExtension()==='png' ) {
        $images[]=$file->getPath()."https://stackoverflow.com/".$file->getFilename();
    }


}

Что можно сделать, чтобы это не было так медленно?

Как я могу оптимизировать поиск?

Ответ или решение

Для эффективного поиска файлов по имени в директории, содержащей миллион файлов, важно использовать оптимизированные подходы, чтобы минимизировать время обработки и улучшить производительность. Ваша исходная реализация с использованием File::allFiles($path) и циклом по всем файлам для фильтрации может быть недостаточно эффективной. Мы рассмотрим несколько стратегий, которые могут существенно ускорить поиск.

1. Использование индексации файловой системы

Одним из самых эффективных способов ускорить поиск является использование индексирования файловой системы. Это позволяет избежать полной проверки каждого файла. Например, в системах на базе Linux можно использовать locate, а в Windows – Everything. Оба этого инструмента создают индексы, доступные для быстрого поиска. В случае с PHP, вы можете интегрировать вызов этих утилит через командную строку и обрабатывать результаты.

Пример использования locate в Linux:

$output = [];
exec("locate -r '\\.jpg$|\\.png$'", $output);
$images = array_map('realpath', $output);

2. Параллельная обработка

Если ваш сервер имеет многоядерный процессор, вы можете воспользоваться параллельной обработкой для одновременного сканирования подкаталогов. Используйте библиотеки для работы с многопоточностью, такие как pthreads или Guzzle.

Пример с использованием Guzzle для параллельных запросов:

// В качестве примера можно использовать Guzzle для запуска нескольких параллельных операций.
// Однако, Guzzle больше подходит для запросов к HTTP.

use GuzzleHttp\Client;

$client = new Client();
$promises = [];
$paths = [...]; // массив путей к директориям

foreach ($paths as $path) {
    $promises[] = $client->getAsync($path);
}

$responses = \GuzzleHttp\Promise\settle($promises)->wait();
$images = [];
foreach ($responses as $response) {
    if ($response['state'] === 'fulfilled') {
        // обработка полученных данных
    }
}

3. Фильтрация на уровне файловой системы

При использовании встроенных функций PHP таких как FilesystemIterator, можно проводить фильтрацию на этапе чтения, что значительно уменьшает количество ненужных операций.

Пример использования FilesystemIterator:

$directory = new RecursiveDirectoryIterator($path);
$iterator = new RecursiveIteratorIterator($directory);
$images = [];

foreach ($iterator as $fileinfo) {
    if ($fileinfo->isFile() && in_array($fileinfo->getExtension(), ['jpg', 'png'])) {
        $images[] = $fileinfo->getPathname();
    }
}

4. Использование кеширования

Если вы будете часто производить поиск по одним и тем же критериям, имеет смысл сохранять результаты в кеш. Это может быть сделано с помощью Redis или Memcached. Простой механизм кеширования может значительно сократить время для последующих поисков.

5. Оптимизация по условиям фильтрации

Если вы точно знаете, что вам нужно только определенное подмножество файлов, попробуйте еще более специфичные условия фильтрации. Например, фильтрация по размеру или времени последней модификации перед проверкой расширения файла.

Заключение

Оптимизация поиска файлов в директории с миллионом файлов подразумевает применение нескольких методов: использование индексации, параллельной обработки, фильтрации на уровне файловой системы, кеширования и смещения фокуса на конкретные условия. Применяя эти подходы, вы значительно ускорите операции фильтрации и поиска, делая процесс более продуктивным и эффективным.

Оцените материал
Добавить комментарий

Капча загружается...