Как же всё запущено

В прошлой части:

  • if быстрее, чем switch;
  • echo быстрее, чем print;
  • явная проверка на (не)нулевое значение медленнее, чем неявная.

А также:

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

Продолжим.

Конкатенация или переменные внутри строки?

  Конкатенация Переменные внутри строки
Код
[-]
View Code PHP
<?php
    $tpl  = "str2";
    $text = 'str1 ' . $tpl . " str3\n";
    echo $text;
?>
[-]
View Code PHP
<?php
    $tpl  = "str2";
    $text = "str1 {$tpl} str3\n";
    echo $text;
?>
Результат
[-]
View Code Text
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   2     0  ASSIGN                                                   $tpl, 'str2'
   3     1  CONCAT                                           ~1      'str1 ', $tpl
         2  CONCAT                                           ~2      ~1, ' str3\n'
         3  ASSIGN                                                   $text, ~2
   4     4  ECHO                                                     $text
   6     5  RETURN                                                   1
         6* ZEND_HANDLE_EXCEPTION
[-]
View Code Text
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   2     0  ASSIGN                                                   $tpl, 'str2'
   3     1  INIT_STRING                                      ~1
         2  ADD_STRING                                       ~1      ~1, 'str1 '
         3  ADD_VAR                                          ~1      ~1, $tpl
         4  ADD_STRING                                       ~1      ~1, ' str3\n'
         5  ASSIGN                                                   $text, ~1
   4     6  ECHO                                                     $text
   6     7  RETURN                                                   1
         8* ZEND_HANDLE_EXCEPTION

Вывод: конкатенация быстрее, и, как показал тест (путём замены echo $text; на echo memory_get_usage();), потребляет меньше памяти.

Цикл со счётчиком: while или for?

  for while
Код
[-]
View Code PHP
<?php
    for ($i=0; $i<1000; ++$i) {
    }
?>
[-]
View Code PHP
<?php
    $i = 0;
    while ($i<1000) {
        ++$i;
    }
?>
Результат
[-]
View Code Text
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   2     0  ASSIGN                                                   $i, 0
         1  IS_SMALLER                                       ~1      $i, 1000
         2  JMPZNZ                                        5          ~1, ->6
         3  PRE_INC                                                  $i
         4  JMP                                                      ->1
   3     5  JMP                                                      ->3
   7     6  RETURN                                                   1
         7* ZEND_HANDLE_EXCEPTION
[-]
View Code Text
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   2     0  ASSIGN                                                   $i, 0
   3     1  IS_SMALLER                                       ~1      $i, 1000
         2  JMPZ                                                     ~1, ->5
   4     3  PRE_INC                                                  !0
   5     4  JMP                                                      ->1
   9     5  RETURN                                                   1
         6* ZEND_HANDLE_EXCEPTION

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

Пустая строка или NULL?

  Пустая строка null
Код
[-]
View Code PHP
<?php
    $a = "";
    echo memory_get_usage();
?>
[-]
View Code PHP
<?php
    $a = NULL;
    echo memory_get_usage();
?>
Результат 106,336 106,224

Вывод: использование пустых значений «сложных» типов (строки, массивы, объекты) ведёт к повышенному потреблению памяти. Использование NULL — самый оптимальный вариант.

is_null() или строгая проверка на NULL?

  is_null Строгое соответствие
Код
[-]
View Code PHP
<?php
    $a = 0;
    if (is_null($a)) {
    }
?>
[-]
View Code PHP
<?php
    $a = 0;
    if ($a === NULL) {
    }
?>
Результат
[-]
View Code Text
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   2     0  ASSIGN                                                   $a, 0
   3     1  SEND_VAR                                                 $a
         2  DO_FCALL                                      1          'is_null'
         3  JMPZ                                                     $1, ->5
   4     4  JMP                                                      ->5
   6     5  RETURN                                                   1
         6* ZEND_HANDLE_EXCEPTION
[-]
View Code Text
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   2     0  ASSIGN                                                   $a, 0
   3     1  IS_IDENTICAL                                     ~1      $a, null
         2  JMPZ                                                     ~1, ->4
   4     3  JMP                                                      ->4
   6     4  RETURN                                                   1
         5* ZEND_HANDLE_EXCEPTION

Вывод: проверка на строгое равенство NULL работает быстрее, в том числе из-за отсутствия необходимости вызова функции.

echo: конкатенация или запятые?

  Конкатенация Запятые
Код
[-]
View Code PHP
<?php
    echo 'Memory ' . 'usage ' . 'is ' . memory_get_usage() . "\n";
?>
[-]
View Code PHP
<?php
    echo 'Memory ', 'usage ', 'is ', memory_get_usage(), "\n";
?>
Результат
[-]
View Code Text
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   2     0  CONCAT                                           ~0      'Memory ', 'usage '
         1  CONCAT                                           ~1      ~0, 'is '          
         2  DO_FCALL                                      0          'memory_get_usage'
         3  CONCAT                                           ~3      ~1, $2            
         4  CONCAT                                           ~4      ~3, '\n'          
         5  ECHO                                                     ~4
   3     6  RETURN                                                   1
         7* ZEND_HANDLE_EXCEPTION
[-]
View Code Text
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   2     0  ECHO                                                     'Memory '
         1  ECHO                                                     'usage '
         2  ECHO                                                     'is '
         3  DO_FCALL                                      0          'memory_get_usage'
         4  ECHO                                                     $0
         5  ECHO                                                     '\n'
   3     6  RETURN                                                   1
         7* ZEND_HANDLE_EXCEPTION
  Memory usage is 106192 Memory usage is 106184

Выводы: в очередной раз менее читабельный метод оказался лучшим — на этот раз в плане потребления памяти. И, как видим, PHP не догадался даже объединить строки вместе.

Что быстрее: статический или динамический метод?

  Динамический метод Статический метод
Код
[-]
View Code PHP
<?php
    class A {
        public function test() {}
    }

    $a = new A;
    $a->test();
?>
[-]
View Code PHP
<?php
    class A {
        public static function test() {}
    }

    $a = new A;
    A::test();
?>
Результат
[-]
View Code Text
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   2     0  NOP                                                                
   6     1  ZEND_FETCH_CLASS                                 :1      'A'      
         2  NEW                                              $2      :1        
         3  DO_FCALL_BY_NAME                              0                    
         4  ASSIGN                                                   $a, $2    
   7     5  ZEND_INIT_METHOD_CALL                            $5      $a, 'test'
         6  DO_FCALL_BY_NAME                              0                    
   8     7  RETURN                                                   1        
         8* ZEND_HANDLE_EXCEPTION
[-]
View Code Text
line     #  op                           fetch          ext  return  operands
-------------------------------------------------------------------------------
   2     0  NOP                                                                
   6     1  ZEND_FETCH_CLASS                                 :1      'A'      
         2  NEW                                              $2      :1        
         3  DO_FCALL_BY_NAME                              0                    
         4  ASSIGN                                                   $a, $2    
   7     5  ZEND_FETCH_CLASS                                 :5      'A'      
         6  ZEND_INIT_STATIC_METHOD_CALL                             null, 'test'
         7  DO_FCALL_BY_NAME                              0                      
   8     8  RETURN                                                   1          
         9* ZEND_HANDLE_EXCEPTION

Выводы: при прочих равных условиях, вызов статического метода на один опкод длиннее вызова динамического метода. Таким образом, если делать все методы класса, которые не используют $this, статическими, это приведёт к потреблению памяти.

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

Добавить в закладки

Связанные записи

7
Окт
2009

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

К статье «PHP: красота кода сказывается на производительности: часть 2» комментариев пока нет. Не хотите ли стать первым?

Подписаться на RSS-ленту комментариев к статье «PHP: красота кода сказывается на производительности: часть 2» Trackback URL: http://blog.sjinks.org.ua/php/651-php-code-beauty-impacts-performance-part-2/trackback/

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

Вы можете использовать данные тэги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

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

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