print или echo, что быстрее?

Original author: Fabien Potencier
  • Translation
Под катом перевод довольно старого поста Фабиена (Fabien Potencier) на тему print vs echo, примечательного, на мой взгляд, методом установления «истины». В отличии от подавляющего большинства подобных исследований, в этом вы не найдете запуска скриптов с echo и print миллионы раз.

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

print vs echo, which one is faster?

Как большинство из нас, я устал читать блог-посты про бессмысленные микро-оптимизации типа замены print на echo, ++$I на $i++ или двойные кавычки на одинарные. Почему? Потому что в 99.999999% случаев, это не имеет значения. Почему? Потому что в 99.99% случаев было бы лучше с вашей стороны, если бы вы установили кешер опкода типа APC, или добавили недостающие в вашей базе индексы, или попробовали не делать те 1000 SQL запросов, которые у вас делаются на главной.

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

Знакомьтесь — VLD — «Vulcan Logic Disassembler». VLD написан Дериком Ризансом (Derrick Rethans) и, как становится ясно при прочтении главной страницы проекта, «VLD цепляется за Zend Engine и делает дамп всех опкодов выполняемого скрипта».

Установка VLD тривиальна — скачиваете и устанавливаете так же как и любое другое расширение php.

phpize
$ ./configure
$ sudo make install

Подключите расширение в php.ini

extension=vld.so

(ну или в каком нибудь /etc/php/apache2/conf.d/vld.ini — вам виднее где это правильнее сделать в вашей ОС прим. пер.)

Время заглянуть под капот. Создайте два файла: один с echo и другой с print
// print.php
<?php print 'foo';

// echo.php
<?php echo 'foo';

Запустите эти скрипты из командной строки с параметрами -d vld.activate=1 чтобы активировать VLD вывод и давайте посмотрим на опкод выданный скриптами.
$ php -d vld.active=1 print.php

number of ops:  4
compiled vars:  none
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   1     0  PRINT                                            ~0      'foo'
         1  FREE                                                     ~0
   2     2  RETURN                                                   1
         3* ZEND_HANDLE_EXCEPTION     

$ php -d vld.active=1 echo.php

number of ops:  3
compiled vars:  none
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   1     0  ECHO                                                     'foo'
   2     1  RETURN                                                   1
         2* ZEND_HANDLE_EXCEPTION            

Нашли отличие? — Да, print использует на один опкод больше, потому, что возвращает что-то. Мы можем заключить, что echo быстрее чем print. Но один опкод ничего не стоит. Правда. Даже если в скрипте сотни вызовов print (вспомни формулу X = E-1 прим. пер.)

Кстати, благодаря тому, что print всегда возвращает 1, вы можете делать интересные штуки типа такой:
// Так нельзя сделать с echo
<?php $isFoo and print 'foo'; ?>


Хотите узнать количество опкода выполняемое при запуске скрипта с кучей инклюдов? Попробуйте так:
$ php -d vld.active=1 print.php 2> output
$ grep "number of ops" output | cut -f 5 -d ' ' | (tr '\n' +; echo 0) | bc

Я попробовал на голом Wordpress. На моем ноутбуке скрипт виснет до тех пор, пока не вываливается с ошибкой «Bus Error», но уже к этому моменту количество опкода зашкаливает за 2.3 миллиона. Этим все сказано.
AdBlock has stolen the banner, but banners are not teeth — they will be back

More
Ads

Comments 35

    +18
    > (привет пользователям M$OS).
    Помечайте хоть отсебятину-то.
      +10
      Тема «print или echo» уже порядком достала, некоторые кодеры даже умудряются в резюме хвастатья знаниями об этом…
      А вот за Vulcan Logic Disassembler спасибо, надо будет попробовать ради интереса на битриксе и прочих крутейших CMS ;))) Ну и заодно свой **внокод прогнать just4fun. Хотя в реальность скорее всего всё упрется не в execution units, а в ожидание ввода/вывод всяких БД и внешних API.
        +19
        Я собственно и делал перевод из желания познакомить людей с VLD, а не чтобы дать ответ на вечный вопрос echo или print, но похоже это мало кто понял.
          +7
          Просто измените заголовок на «Применение Vulcan Logic Disassembler для анализа кода PHP».
            +7
            Нет. Во-первых это все-же перевод. Во-вторых, для меня, кармы и рейтинги это показатель отношения читателя. Я пишу что-то на хабре для вас, а не для рейтингов, кармы, денег или вселенской славы и если средний хаброюзер способен заминусовать статью за заголовок, даже не читая её, или прочитав неспособен уловить суть, то что я могу сказать..? Я не буду прикрывать этот его позор, а отнесусь к этому кейсу как к показательному исследованию. Вспоминаю опрос от автором Денвера. Он тогда добавил в заголовок, что он автор Денвера и ушел из глубокого минуса, а зря, люди должны получать то чего действительно заслуживают и первые результаты того его поста были более авторитетными чем те, которые он получил после того как поклонился дуракам.
        +3
        Сделал вот такой тест:

        user@meowr /tmp/php $ php echo.php | pv > /dev/null
        ^C,8MiB 0:00:09 [7,76MiB/s] [                    <=>                                                                                                ]
        
        user@meowr /tmp/php $ php print.php | pv > /dev/null
        ^C,3MiB 0:00:08 [8,15MiB/s] [                  <=>                                                                                                  ]
        
        user@meowr /tmp/php $ cat echo.php 
        <?php while (1) { echo 'wat'; } ?>
        user@meowr /tmp/php $ cat print.php 
        <?php while (1) { print 'wat'; } ?>
        

        print использует на опкод больше, но при этом скорость дает чуть-чуть большую (и это не мгновенное явление, я проверял несколько раз)
        Интересно, с чем это связано? Или я что-то делаю не так?
        Интерес чисто спортивный, никакого отношения к php не имею
          +1
          Одно дело опкоды скрипта, а другое дело сами функции вызываемые в скрипте. print может оказаться программно, намного короче чем echo. В общем для этого надо посмотреть непосредственно исходники php
            0
            Даже не читая ведь код, видно, что вся в разница в том, что появляется код возврата.

            Код обработчика опкодов
            ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMP|VAR|CV, ANY)
            {
            	USE_OPLINE
            	zend_free_op free_op1;
            	zval *z;
            
            	SAVE_OPLINE();
            	z = GET_OP1_ZVAL_PTR(BP_VAR_R);
            
            	if (OP1_TYPE == IS_TMP_VAR && Z_TYPE_P(z) == IS_OBJECT) {
            		INIT_PZVAL(z);
            	}
            	zend_print_variable(z);
            
            	FREE_OP1();
            	CHECK_EXCEPTION();
            	ZEND_VM_NEXT_OPCODE();
            }
            
            ZEND_VM_HANDLER(41, ZEND_PRINT, CONST|TMP|VAR|CV, ANY)
            {
            	USE_OPLINE
            
            	ZVAL_LONG(&EX_T(opline->result.var).tmp_var, 1);
            	ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ECHO);
            }
            
              0
              вся разница
              Не вся. print кушает один параметр, а echo может и несколько. Хотя из этого куска кода этого почему-то не видно
                0
                предположу, что в случае вывода через запятую код транслируется не в один ZEND_ECHO, а в столько, сколько нужно вывести.
              0
              Если судить по исходникам, то print базируется на echo и лишь устанавливает значение результата в единицу.

              опоздал…
            –13
            February 04, 2009
            Очень актуальная тема, продолжайте переводить!
              +16
              Я впервые слышу про Vulcan Logic Disassembler, так что пользительно и интересно.
                +4
                А начало поста «Под катом перевод довольно старого поста Фабиена» вам как бы ничего не сказало пока вы оригинал не открыли, да?
                –2
                При условии, что echo/print должен быть вызван только один раз (это в идеале), то данное исследование ещё более странным кажется.
                  +2
                  Не обязательно. Вызовов может быть много в шаблонизаторе.
                    0
                    Чем обусловлен такой идеал? Тело ответа может составлять мегабайты, нужно постоянно держать его в памяти и дописывать а-ля $body .= "<h1>$title</h1>"; (а это постоянные перераспределения памяти и копирование)?
                      0
                      В любом случае у вас вывод тела ответа будет приблизительно в одном месте. А так да, случаи бывают разные, хоть сходу и не придумаю варианта с мегабайтным телом ответа… Даже если речь идет о отдаче файла или генерации изображений, проще записать в файл (куда всеравно нужно будет записывать) и отдавать через sendfile. Хотя случаи разные бывают.
                        0
                        Вывод тела у меня будет размазан по шаблонам и лэйаутам. Где-то, возможно, он будет перехватываться ob_*(), а где-то уходить прямо в stdout, но мне не нужно будет об этом думать.
                    +1
                    Мы можем заключить, что echo быстрее чем print.
                    Откуда взялся такой глупый необоснованный вывод? Не можем — опкоды выполняются не за одинаковое время.
                      +1
                      И что что они выполняются за неодинаковое время? print всегда будет медленнее echo за счет того, что print должен вернуть значение. Другое дело что даже на большом количестве итераций преимущество если и будет, то оно будет настолько небольшим что можно и забить.

                      Да и вообще не вижу смысла для холивара, и у print и у echo есть свои особенности, которые могут быть полезны в разных ситуациях.
                        –2
                        Может и медленнее, но из приведенных выше данных этого не следует.
                      –1
                      В первом абзаце чувствую ненависть автора к своим падаванам :)
                        0
                        Поясните?
                          0
                          Потому что в 99.999999% случаев, это не имеет значения. Почему? Потому что в 99.99% случаев было бы лучше с вашей стороны, если бы вы установили кешер опкода типа APC, или добавили недостающие в вашей базе индексы, или попробовали не делать те 1000 SQL запросов, которые у вас делаются на главной

                          Вещи настолько очевидные, что напоминать о них в данном контексте, на мой взгляд, — это троллинг. Намекая на «99.999999% из вас слишком неопытны»

                          P.S. Ничего не имею против php в умелых руках.
                            0
                            микрооптимизаторы, заменяющие двойные кавычки на одинарные, как раз неопытны, все верно
                              0
                              Пример того как два человека могут смотреть на одно и то же, но видеть это по-разному ((с)). Я вот ничего кроме опытности и как следствие трезвого отношения к вопросу в этих словах не увидел. Ну разве еще самокритику, но её я как то плохо передал переводом. Хотя, может это была просто проекция.
                          +2
                          Можно посмотреть online на опкоды: 3v4l.org/BtS8r/vld#tabs
                            0
                            print vs echo, which one is faster?

                            А почему не перевели этот заголовок?
                              0
                              В вопросе что быстрее print или echo победил ?>foo< ?=$foo?>bar
                                +1
                                Как большинство из нас, я устал читать блог-посты про бессмысленные микро-оптимизации типа замены print на echo, ++$I на $i++ или двойные кавычки на одинарные. Почему? Потому что в 99.999999% случаев, это не имеет значения. Почему? Потому что в 99.99% случаев было бы лучше с вашей стороны, если бы вы установили кешер опкода типа APC, или добавили недостающие в вашей базе индексы, или попробовали не делать те 1000 SQL запросов, которые у вас делаются на главной.

                                Стрелки 80-ого левела. Почему бы сразу не взять в привычку писать одинарные кавычки, echo и $i++?
                                  0
                                  Обычно так и делают. Вообще смысл статьи в дампере опкодов, а не в том, что быстрее. Это всяко интереснее. То что echo/print будет являться узким местом в приложении конечно смешно слушать.
                                    0
                                    Кстати, строки с одинарными кавычками не всегда быстрее строк с двойными кавычками. И, наверное, Вы имели в виду ++$i?
                                      0
                                      Как минимум, потому что есть соглашения, улучшающие читаемость кода, пускай и несколько его замедляющие.
                                      0
                                      теперь мне совершенно ясно, что можно написать вот так:
                                      print print print print print print print print 1;
                                      и оно отработает )

                                      Only users with full accounts can post comments. Log in, please.