Ответ на «микрооптимизацию в PHP» / PHP. Производительность


Оригинал: A Response to “Micro-Optimizations in PHP”

На прошлой неделе я прочитал пост, рекомендованный мне в PHP Weekly. Он назывался Микрооптимизация в PHP. Я повелся, ведь всегда стремлюсь быть лучшим PHP разработчиком. Пост начинается с общих рекомендаций, которые, по сути, являются даже не микро-, а микро-микрооптимизацией. Продолжая читать, я приходил к выводу, что описанное в тексте и вовсе имеет мало общего с оптимизацией. В итоге я могу сказать, что пост был написан безответственно — заявления автора не имели обоснований.

Обидно, что я получаю такие низкокачественные посты из рассылки PHP. Подобные статьи путают разработчиков, что, в свою очередь, способствует созданию некачественных приложений в сообществе PHP-разработчиков. Эта ситуация заставляет задуматься о росте числа хейтеров PHP.

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

Foreach против for


Ложь.

foreach работает быстрее, если цикл используется для чтения массива. Если вам нужно записать что-то в массив, то foreach значительно ухудшит производительность. Здесь самое место циклу for.

Другой случай, когда лучше использовать for — блок, содержащий логику подсчета.

Смотрите сами:
for ($i = 0; …; ++$i) { 
    // block 
}

Для foreach эквивалентно:
$i = 0; 
foreach (…) { 
    // block 
    ++$i; 
}

Исключение: Если цикл используется в численно индексированном массиве, то ключ массива может служить счетчиком.

Истина.


Две абсолютные правды при использовании цикла for:

  1. Предварительно рассчитывайте части условия выражения. Условие в цикле for оценивается на каждой итерации. Избежание перезагрузок вызова функций, которые возвращают значение, не меняющееся в течение цикла, оптимизирует ваш код.
  2. Используйте преинкремент. По своей природе преинкремент быстрее.

Код:
$count = count($arr);
for ($i = 0; $i < $count; ++$i) { 
    // block 
}


Двойные кавычки против одинарных


Ложь.
Еще в 2007 году Илья Альшанецкий сообщил мне по электронной почте о некоем Оптимизационном мифе. И все-таки это были времена PHP 4. Где-то в PHP 5 двойные кавычки были оптимизированы (я слышал о PHP 5.1).

То, что двойные кавычки работают быстрее, чем одинарные, ни чем не обосновано. Если в строке не используются переменные, само собой разумеется, что одинарные кавычки обрабатываются быстрее. Кроме того, буквенные значения (одинарные кавычки) могут быть оптимизированы в памяти.

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

UNION против OR


Ложь.

Я сейчас читаю книгу под названием Высокооптимизированный MySQL. На самом деле, я только что закончил главу, посвященную оптимизации запросов. Эта рекомендация фактически направила меня на путь написания ответного поста. Заявление автора, что надо заменить все ` OR ` на ` UNION ` просто безрассудно.

Во-первых, оригинальный пример плохой. Предлагается заменить следующее:

select username from users where company = ‘bbc’ or company = ‘itv’;

на:
select username from users where company = ‘bbd’ 
union 
select username from users where company = ‘itv’;

При использовании одной и той же колонки, по заявлению автора, его решение более производительно. То есть вы должны заменить UNION на OR, причем WHERE продолжает работать на той же колонке.

Во-вторых, замена OR на UNION в запросах не может вернуть один и тот же результат. В то же время использование UNION может быть связано с оптимизацией, но вы должны понимать, когда использовать его. Не стремитесь заменить OR на UNION во всем коде.

Я все еще учусь MySQL-оптимизации, и отправил эту тему в сообщество StackOverflow. Я призываю вас прочитать
ответы для получения более подробной информации о том, почему противопоставление UNION и OR не всегда является оптимизацией.

Дополнительная PHP-оптимизация


В исходной статье было несколько верных советов по оптимизации:

  1. Используйте echo вместо print. Истина.
  2. Используйте строковые функции через регулярные выражения. Это спараведливо, за исключением сложного сопоставления с образцом. Эквивалентный регулярным выражениям код, написанный с использованием строковых функций, будет более производительным. Об этом говорится в PHP-документации для функции регулярных выражений.

Правило 80/20 в производительности


Производительность также подчиняется правилу 80/20. Если употребление одинарных кавычек превышает двойные на 80% — вы оптимизированы. Поздравляю. Вы можете идти домой.

Запомните


Серебряной пули не существует. Будьте скептиком абсолютной отчетности. Система имеет много нюансов. То, что работает для кого-то, может не работать для вас. Если в чем-то сомневаетесь, то лучше проверьте это сами.

Ссылки


Если вы заинтересованы в повышении производительности и оптимизации PHP, можете посетить следующие ресурсы:

Кроме того, почаще заглядывайте в документацию PHP. Там содержится ценная информация в виде описания функций и комментариев пользователей.