Навеяно вот этим.
Я решил вспомнить некоторые особенности PHP, связанные с производительностью.
Отмечу, что включил в свой небольшой список лишь то, что обычно вызывает удивление у junior developers, с которыми мне приходилось работать.
О банальных вещах, вроде «одинарные кавычки вместо двойных», думаю, знают все, поэтому постараюсь кого-нибудь удивить.
Результаты и выводы, сделаны на основании нескольких версий PHP, который крутятся на знакомых мне серверах, а именно 5.2.6 из Debian Lenny, 5.3.2 из Ubuntu, и 5.2.14 из dotdeb. Возможно, на других платформах, есть отличия.
Все выводы получены в результате личных наблюдений и тестов.
Вполне возможно, что на вашей системе результаты будут иные.
Замечу, что многое зависит от вашей архитектуры, и практически любой совет надо проверять на своём коде, не доверяя полностью чужому опыту.
Поэтому я осознанно не указывал абсолютных цифр, которые вы можете найти и сами, к примеру на http://phpbench.com/ (не моё)
Удачи и быстрого кода!
Я решил вспомнить некоторые особенности PHP, связанные с производительностью.
Отмечу, что включил в свой небольшой список лишь то, что обычно вызывает удивление у junior developers, с которыми мне приходилось работать.
О банальных вещах, вроде «одинарные кавычки вместо двойных», думаю, знают все, поэтому постараюсь кого-нибудь удивить.
Результаты и выводы, сделаны на основании нескольких версий PHP, который крутятся на знакомых мне серверах, а именно 5.2.6 из Debian Lenny, 5.3.2 из Ubuntu, и 5.2.14 из dotdeb. Возможно, на других платформах, есть отличия.
- file_get_contents
Не секрет, что file_get_contents, использует (memory mapping), прирост от которого, особенно заметен на крупных файлах.
Следствие этого:
simplexml_load_string( file_get_contents ('file.xml') )
работает быстрее, чем:
simplexml_load_file('file.xml')
Похоже, что подобные simplexml_load_file функции, базируются на обычных fopen/fread, что приводит к разнице в скорости.
NB: Также неплохо ускоряется DOM->loadFile, и некоторые другие функции с похожим поведением.
Если вы разбираете файл с \n разделителями (или к примеру CSV, TSV, или нечто подобное), советую заменить file() на
explode(PHP_EOL, file_get_contents('file.xml'));
Спасибо за подсказку c PHP_EOL LoneCat
Прирост будет еще больше, чем в случае с xml.
Видимо, file() — не очень удачно реализована.
- count() и sizeof()
UPD: sizeof() это синоним count(), работает быстрее, спасибо merkushin за поправку.
- Notices, etc.
Допускать нотисы, это ужасно, да.
Но если ваш junior developer, не хочет признавать их важность, расскажите ему, что на генерацию одного notice у PHP уходит время, за которое можно обойти и инкрементировать массив из примерно 30-ти элементов.
- foreach
Цикл foreach, практически в каждой статье, посвящённой производительности PHP, предают анафеме.
На практике, не всё так страшно. Жуткие конструкции, вроде:
while (list($key, $value) = each($item))
в реальных условиях, часто бывают медленнее.
Если же пропустить $key, то эта конструкция проигрывает foreach примерно 30-40%.
- JSON vs XML
Скажу лишь, что перейдя на json-файлы для конфигурации, выиграл 20-30% на инициализации ядра. JSON приятен для глаз, иерархичен и быстр.
Также, json_decode быстрее работает без второго аргумента (генерируя объект, а не массив), но незначительно.
- mb_ereg vs preg_match
POSIX — выражения медленные, это опять же, общеизвестно.
Но движок Oniguruma, который используется в функции mb_ereg, и её mb-собратьях, с этим не согласен, и примерно в двух третях случаев, обгоняет хвалёный preg_match.
- IGBinary для сериализации.
Это очень быстрое расширение, с очень компактным значением на выходе.
- file_exists и include
Проверять file_exists() затем делать include, дешевле, чем проверять возврат include(), если вы, к примеру, не уверены, что файл на месте.
- Опять include
Не знаю почему, но include_once, часто проигрывает по скорости конструкции с принудительной проверкой (записываем в массив все включённые файлы).
- Static vars
Статическая переменная класса, самое лучшее место для быстрого получения глобальных данных, замечен прирост в 5 — 10 раз.
- Напоследок, пара советов
Показывайте себе время выполнения в миллисекундах, а не в долях секунды.
Это здорово мотивирует (сравните, «100 миллисекунд» и «0.1 секунды»), и легче читается.
Очень важно, собирать информацию, не только об абсолютной скорости, но и анализировать вклад отдельных подсистем: ядра, интерфейса данных, рендеринга, и.т.п.
Свой профайлер, я настроил (на testing-машине) на выброс исключений, при аномальном замедлении каких-либо участков кода (пример: «Achtung! 30% времени на подключение к MySQL»).
Все выводы получены в результате личных наблюдений и тестов.
Вполне возможно, что на вашей системе результаты будут иные.
Замечу, что многое зависит от вашей архитектуры, и практически любой совет надо проверять на своём коде, не доверяя полностью чужому опыту.
Поэтому я осознанно не указывал абсолютных цифр, которые вы можете найти и сами, к примеру на http://phpbench.com/ (не моё)
Удачи и быстрого кода!