Как же всё запущено
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). Пусть результат от одной сэкономленной спички ничтожно мал, но помноженный на количество таких потенциальных спичек во всём коде, становится весьма и весьма ощутимым, особенно на слабом железе.