scandir () в PHP слишком медленный

0

Целевой каталог содержит 10 million+ текстовых файлов. using $a = scandir() на веб-странице смертельно медленное. Требуется массив результатов менее чем за две секунды. Фильтрация не работает (также просматривает весь список)

все, что я могу придумать, это использовать программу perl или c для предварительной обработки и заполнения x тысяч имен файлов из целевого каталога в файл, пометить имена файлов в целевом каталоге, выбранном с помощью .pi в конце (или что-то), и использовать php file() чтобы получить список из файла.

Мне нужно открыть и работать с каждым файлом, прежде чем он будет забит в таблицу. FYI. Я не могу дождаться более 1-2 секунд, чтобы массив работал, чтобы быть доступным. Любая помощь была оценена. Память не является проблемой. hdd пространство не является проблемой, мощность процессора не является проблемой. проблема заключается в получении списка в массиве Fast при использовании интерфейса веб-страницы. Я не могу ждать, потому что я устал ждать.

Я попытался использовать краткую быструю программу c с opendir и readdir но даже для сканирования списка каталогов требуется почти 4 минуты. по крайней мере, я мог бы поставить на него губернатора, чтобы ограничить файлы x.

Кажется, что ответ заключается в вызове программы perl или c которую я могу ограничить файлами x, и я могу назвать это с помощью system() или backticks. Затем этот список можно открыть с помощью file()... OTF... имеет смысл?

  • 6
    Любой отдельный каталог с 10 миллионами файлов будет медленным - ужасно медленным. Как правило, тысячи файлов - это слишком много. Вам нужно реорганизовать каталог, а не беспокоиться о переопределении в C ( scandir() реализован в C - это не будет иметь большого значения).
  • 0
    да, подумал об этом ... вы правы, мне, вероятно, придется переписать его в сборке, и к тому времени, когда я получу это, scandir () будет готово :-)
Показать ещё 5 комментариев
Теги:
readdir
scandir

2 ответа

7

Проблема в том, что меньше PHP и больше файловой системы. Большинство файловых систем не работают с 10 миллионами файлов в одном каталоге, и производительность начинает сильно страдать. Вероятно, вы вряд ли получите гораздо лучшую производительность из-за перезаписи на C или Perl, потому что файловая система просто перегружена, а ее производительность стала патологической.

Сначала переключитесь с scandir на opendir и readdir. Это позволяет избежать создания массива из 10 миллионов элементов. Это также позволяет вашей программе начать работу сразу же, перед тем, как кропотливо прочитать 10 миллионов имен файлов.

if ($dh = opendir($dir)) {
    while (($file = readdir($dh)) !== false) {
        ...do your work...
    }
    closedir($dh);
}

Во-вторых, измените структуру своего каталога на наличие как минимум двух уровней подкаталогов на основе первых букв имен файлов. Например, t/h/this.is.an.example. Это уменьшит количество файлов в одном каталоге до уровня, который может лучше обрабатывать файловая система.

3

Вы можете написать программу на языке C которая вызывает getdents getdents. Используйте большой размер буфера, например 5 МБ, и пропустите записи с inode == 0, чтобы значительно повысить производительность.

Решения, которые полагаются на libc readdir(), медленны, потому что они ограничены чтением 32K кусков записей в каталоге за раз.

Этот подход описан в блоге Olark Developers Corner, приведенном ниже.

Рекомендации:

Ещё вопросы

Сообщество Overcoder
Наверх
Меню