Дебаты о производительности PHP file() против fopen()+fgets()

Я нахожусь в процессе переписывания некоторых скриптов для анализа сгенерированных машиной журналов с perl на php. Размер файлов варьируется от 20 МБ до 400 МБ. Я сталкиваюсь с этой проблемой, чтобы решить, следует ли мне использовать комбинацию file () или fopen () + fgets (). через файл для более быстрой работы.

Вот базовое прохождение, я проверяю размер файла перед его открытием, и если файл больше 100 МБ (довольно редкий случай, но время от времени случается), я пойду по маршруту fopen + fgets, так как я только наткнулся на ограничение памяти для сценария до 384 МБ, любой файл размером более 100 МБ может вызвать фатальную ошибку. В противном случае я использую файл().

Я просматриваю файл только один раз от начала до конца в обоих методах, построчно.

Вот вопрос, стоит ли сохранять часть кода file() для работы с небольшими файлами? Я не знаю, как именно file() (я также использую опцию SKIP_EMPTY_LINE) работает в php, он отображает файл в память напрямую или построчно пихает в память, проходя через него? Я провел на нем несколько тестов, производительность довольно близка, средняя разница составляет около 0,1 с для файла размером 40 МБ, а file() имеет преимущество перед fopen + fgets примерно в 80% случаев (из 200 тестов на одном и том же наборе файлов).

Удаление файловой части может сэкономить мне часть памяти из системы, и, учитывая, что у меня одновременно запущено 3 экземпляра одного и того же скрипта, это может сэкономить мне 1 ГБ памяти в системе 12 ГБ, в которой также размещена база данных и другие дерьмо. Но я также не хочу снижать производительность скрипта, поскольку в день поступает около 10 000 таких журналов, разница в 0,1 с на самом деле складывается.

Любое предложение поможет и TIA!


person Gäng Tian    schedule 04.05.2012    source источник
comment
Вы можете просто написать простой скрипт, чтобы запустить его x раз в одну сторону и вывести время, затраченное на просмотр использования памяти, а затем запустить его снова x раз в другую сторону. Это позволит вам узнать, как они оба работали с вашими данными в ваших системах, и кто из них оказался победителем.   -  person Anigel    schedule 04.05.2012
comment
Я думаю, вам лучше написать одну реализацию и заставить ее работать хорошо. Чтение одной (или n) строк файла за раз, интерпретация/перевод и запись вывода на диск или без него будут работать для файлов всех размеров. Поддержка другого решения добавляет сложности и времени разработчика, которое всегда дорого. Похоже, что размер памяти является вашим ограничивающим фактором, и вы не достигли барьера для времени выполнения. Я хотел бы дать вам больше идей по улучшению производительности, но я чувствую, что это будет не так; Можете ли вы уточнить, как выглядят/нужны ввод и вывод?   -  person Patrick M    schedule 04.05.2012
comment
Входные данные представляют собой какой-то журнал гигантского размера, сгенерированный машиной, в котором есть данные повсюду, а не в едином формате строки, и мне нужно проанализировать из него разные данные. Итак, более подробно, для каждого типа данных у него есть свой класс/объект, чтобы отслеживать, на каком этапе он находится, и после того, как полная строка данных будет сформирована, выгрузите ее в файл csv, который позже будет объемным загрузить в базу данных. Сама память, если я могу получить значительный прирост производительности, я не против выложить 1Gb. Но основывайтесь на эталонном тесте с разницей в микросекундах php. Что касается времени выполнения, я как бы на краю этого.   -  person Gäng Tian    schedule 05.05.2012
comment
и переход к маршруту памяти, похоже, не уведет меня далеко от этого края. Чтение файла в память и процесс раньше были быстрыми в Perl, но поскольку данные становятся все более и более сложными, мне нужна поддержка объектов для поддержания чистого кода, и я вообще не очень хорошо разбираюсь в Perl, поэтому переключаюсь на php. Я думаю, что мой вопрос больше о том, как file() в php фактически сопоставляет файл с памятью, если он проходит его от начала до конца один раз, я думаю, что ответ ясен, я должен отказаться от этой идеи: исправление x к последнему комментарию . file() имеет преимущество ~ 0,1 с в 80% случаев, в противном случае отстает на 0,2 ~ 3 с   -  person Gäng Tian    schedule 05.05.2012


Ответы (1)


Я бы предложил придерживаться одного механизма, например foreach(new \SplFileObject('file.log') as $line). Разделите входные файлы и обработайте их параллельно, 2-3 раза на ядро ​​ЦП. Бонус: более низкий приоритет, чем база данных в той же системе. В PHP это означало бы одновременное создание N копий скрипта, где каждая копия имеет свой собственный список файлов или каталог. Поскольку вы говорите о перезаписи и производительности ввода-вывода, рассмотрите здесь другие платформы с большими возможностями, например Java 7 NIO, асинхронный ввод-вывод nodejs, C# TPL.

person Community    schedule 05.05.2012