2015-03-27 9 views
0

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

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

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

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

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

+5

Любой отдельный каталог с 10 миллионами файлов в нем будет медленным - ужасно медленно. В тысячах файлов слишком много, как правило. Вам нужно реорганизовать каталог, а не беспокоиться о переопределении в C ('scandir()' также реализован в C тоже - он не будет иметь такой большой разницы). –

+0

Да, подумал об этом ... вы правы, мне, вероятно, придется переписать его в сборке, и к тому времени, когда я это заработаю, scandir() будет выполнен :-) –

+0

Вы использовали бы 'opendir()' и 'readdir()' системные вызовы в сборке, и они займут много времени. Вам, вероятно, нужна многоуровневая иерархия каталогов. Простая схема будет принимать первый символ для первого уровня, второй (или первый и второй символы) для второго уровня и заданный размер системы, возможно, третий (или первый-третий символ) для третьего уровня. Если первые три символа являются алфавитами и более или менее равномерно распределены по 26-буквенному алфавиту (что маловероятно), вы получите около 600 файлов на суб-поддиректорию третьего уровня. –

ответ

6

Проблема в том, что 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. Используйте большой размер буфера, например 5 МБ, и пропустите записи с inode == 0, чтобы значительно повысить производительность.

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

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

Ссылки: