PHP: красота кода сказывается на производительности

Читабельный код выполняется медленнее

Недавно я для себя открыл, что PHP не умеет оптимизировать код, а тут новый удар: оказывается, что красота кода отрицательно влияет на производительность. Как и в прошлый раз, для проверки гипотез использовался Vulcan Logic Disassembler. Сравнивались два куска кода: Тест №1: <?php $a = true; if (true == $a) { print 1; } ?> и [...]

← Вернуться к полной версии записи «PHP: красота кода сказывается на производительности»…

Автор: ; опубликовано в: PHP; метки: eAccelerator, PHP, оптимизация, производительность
25
Сен
2009

RSS Комментарии к статье «PHP: красота кода сказывается на производительности» (11)  »

  1. Одно обидно: из eAccelerator 0.9.6-rc1 выкинули оптимизатор и кучу всего остального, оставив только кэширование опкода.

  2. Интересно протестировать связку APC + optimizer.

  3. Ну спички же форменные. Да и как это будет сказываться на «производительности» самого интерпретатора?

    • Спички спичками, но есть несколько нюансов:

      1. Я работаю над проектом в котором одна из задач — массовая рассылка писем подписчикам. Каждое письмо «персонализируется» и т.п., затем отсылается. Подписчиков много тысяч. Слабое место отнюдь не почтовик, а PHP. Он реально тормозит. Множество спичек в цикле, выполняющемся десятки тысяч раз — это очень ощутимо. Говорю потому, что снёс xCache и поставил eAccelerator и включил оптимизатор. Рейт отправки вырос на 30%.
      2. На хорошо нагруженных сайты типа littlefox.ru работа оптимизатора очень заметна — по падению Load Average и сниженной нагрузки на процессор. Железо на сервере не самое мощное, но оптимизация реально творит чудеса (я говорю не только про спички — пришлось написать пару плагинов и даже расширений PHP, чтобы компенсировать тормоза WordPress).

      Вообще мне на ум приходит сравнение программ, скомпилированных Turbo Pascal 7.0 и Borland C++ 3: в Turbo Pascal оптимизатор отсутствует в принципе, а в BC++ его можно включить. Разница ощутима.

      Я натравил оптимизатор на устаревшую локальную копию своего блога (интерпретатор обломался где-то после загрузки плагинов) и сравнил размер выдачи VLD:

      • Без оптимизатора: 184,128 строк
      • С оптимизатором: 180,707 строк

      Разница (для не полностью загруженного WP) составляет 3,421 опкод. Полагая, что опкод выполняется 0.5 микросекунды (думаю, что для дешевых VPS это где-то рядом), имеем разницу в 1.7 миллисекунды. На полностью загруженном WordPress разница будет видна сильнее. Использование оптимизатора — бесплатный способ снизить нагрузку на сервер.

      Да и как это будет сказываться на “производительности” самого интерпретатора?

      Положительно. Компиляция и оптимизация будут выполнены один раз, после чего результат будет закэширован в shared memory.

  4. leo

    Почему вы считаете, что

    5 PRINT
    6 FREE

    работает медленнее

    5 ECHO

    ?

    в остальных рассуждениях подобный косяк повторяется.

    • Очевидно потому, что копался во внутренностях Zend Engine.

      Во-первых, лишний опкод производительности не добавляет (из-за издержек на его анализ/выполнение).
      Во-вторых, внутренняя реализация print вызывает echo, из-за чего print не может быть быстрее:

      [-]
      View Code C
      static int ZEND_PRINT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
      {
          zend_op *opline = EX(opline);

          Z_LVAL(EX_T(opline->result.u.var).tmp_var) = 1;
          Z_TYPE(EX_T(opline->result.u.var).tmp_var) = IS_LONG;

          return ZEND_ECHO_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
      }

      В-третьих, оптимизаторы неспроста PRINT/FREE преобразовывают в ECHO.

      • leo

        Вы меня не поняли и забавно реагируете.
        Никто не утверждал, что лишний опкод добавляет производительность, но вовсе не факт, что print + free выполняется медленнее, чем echo. Я пишу о том, что рассуждение о скорости глядя на внутренние опкоды php, которые вызывают функции, без приведения листингов этих функций бессмысленно. Вот еще пример:
        «Конкатенация или переменные внутри строки»

        CONCAT
        CONCAT

        и

        INIT_STRING
        ADD_STRING
        ADD_VAR
        ADD_STRING

        Можно предположить, что второй блок выполняется медленне, но утверждать этого нельзя.

        Приведённая цитата на Си вообще непонятно, как относится к вопросу.
        Про оптимизаторов довод единственно-хороший, но я впервые слышу это утверждение, а никаких ссылок в вашем сообщении нет.

        • но вовсе не факт, что print + free выполняется медленнее, чем echo

          Ну почему же? Внутренняя реализация print вызывает внутреннюю реализацию echo. Уже только поэтому print не может быть быстрее. Ну и еще необходимость выполнения FREE.

          без приведения листингов этих функций бессмысленно

          Эм… Листинг обработчиков опкодов занимают порядка мегабайта. На мой взгляд, приводить их несколько нецелесообразно. Тем более, что в них интенсивно используются внутренние макросы Zend Engine, которые не всегда очевидны.

          Можно предположить, что второй блок выполняется медленне, но утверждать этого нельзя

          Если Вы познакомитесь с Zend Engine поближе, то можно :-)

          INIT_STRING выделяет один байт памяти и создаёт строковую переменную.
          ADD_STRING вызывает функцию add_string_to_string().
          ADD_VAR преобразует переменную в строку и вызывает ту же add_string_to_string().

          CONCAT вызывает функцию concat_function(), которая по функциональности эквивалентна ADD_VAR (с той разницей, что concat_function() не производит действий, характерных для обработчика опкода).

          Что concat_function(), что add_string_to_string() — это, по сути, erealloc() + memcpy().

          В первом случае получаем два распределения памяти и копирования, во втором — три (это не считая выделения однобайтового буфера). Плюс во втором случае получаем два лишних опкода, которые, к тому же, занимают место в памяти (причём нельзя сказать, что очень мало).

          Приведённая цитата на Си вообще непонятно, как относится к вопросу.

          Видите? Если бы я приводил код всех обработчиков, было бы мало смысла :-) Та цитата показывает, что обработчик PRINT создаёт целочисленную переменную (возвращаемое значение) и вызывает обработчик ECHO. Но с используемыми именами макросов это не очевидно :-)

          но я впервые слышу это утверждение, а никаких ссылок в вашем сообщении нет

          Всё-таки Вы невнимательно читали:

          После этого я собрал (с поддержкой оптимизатора) и поставил eAccelerator и повторил тесты. Тест №1 и тест №2 дали одинаковый результат. Что характерно, eAccelerator самостоятельно преобразовал print в echo. Лапочка. Для теста №3 результат остался неизменным: там, собственно, нечего оптимизировать. А результаты теста №4 впечатлили.

          Ну и плюс листинги.

  5. [...] оптимизатор, встроенный в eAccelerator, то можно повысить производительность PHP-кода. Анализ производительности MySQL-запросов и знание [...]

  6. Tima

    Владимир!))) молодец, четко все расписал, как в статье так и в каментах))

Пожалуйста, не используйте эту форму для комментирования! Данная форма предназначена исключительно для ботов.

Оставить комментарий к записи «PHP: красота кода сказывается на производительности»

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*

Можно использовать следующие HTML-теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, вы выражаете своё согласие с Правилами комментирования.

Подписаться, не комментируя

गते गते पारगते पारसंगते बोधि स्वाहा