echo vs print и "40 советов по оптимизации вашего PHP-кода"

Главные вкладки

Аватар пользователя KalanSPb KalanSPb 3 апреля 2008 в 13:31

С первых часов знакомства с Drupal очень удивил тот факт, что повсеместно используется print, а не привычное мне еще с php3 echo, пришлось даже в мануал лезть разок, чтобы посмотреть отличия, но как-то не особенно беспокоило.

И тут наткнулся натолкнулся на 40 советов по оптимизации вашего PHP-кода - перевод 40 Tips for optimizing your php code

Quote:

  1. Если метод может быть статическим, объявляйте его статическим.
  2. echo быстрее, чем print.
  3. Передавайте в echo несколько параметров, вместо того, чтобы использовать конкатенацию строк.
  4. Устанавливайте максимальное количество проходов ваших циклов for до цикла, а не во время его выполнения.
  5. Удаляйте свои переменные для освобождения памяти, тем более, если это большие массивы.
  6. Остерегайтесь магических методов, таких как __set, __get, __autoload.
  7. require_once дорого обходится.
  8. Указывайте полные пути в конструкциях include/require, меньше времени будет тратится на поиск файла.
  9. Если вам необходимо определить время, когда скрипт был запущен, используйте $_SERVER[’REQUEST_TIME’] вместо time().
  10. Старайтесь использовать strncasecmp, strpbrk и stripos вместо регулярных выражений.
  11. str_replace быстрее, чем preg_replace, но strtr быстрее, чем str_replace.
  12. Если функция, как и функции замены строк, может принимать в аргументы как массивы, так и одиночные символы, и если ваш список аргументов не слишком длинный, подумайте над тем, чтобы записать несколько одинаковых выражений замены, проходя один символ за раз, вместо одной строки кода, которая принимает массив как аргумент поиска и замены
  13. Лучше выбирать утверждения при помощи конструкции else if, чем использовать несколько конструкций if.
  14. Подавление ошибок при использовании @ работает очень медленно.
  15. Используйте модуль Apache mod_deflate.
  16. Закрывайте свои соединения с БД, когда закончите работать с ними.
  17. $row['id'] в семь раз быстрее, чем $row[id].
  18. Сообщения об ошибках дорого стоят
  19. Не используйте функции внутри условия цикла for, например как здесь: for ($x=0; $x < count($array); $x). В данном случае функция count() будет вызываться с каждым проходом цикла.
  20. Инкремент локальной переменной в методе - самый быстрый. Почти также работает инкремент локальной переменной в функции.
  21. Инкремент глобальной переменной в два раза медленее, чем локальной.
  22. Инкремент свойства объекта (т.е. $this->prop++) в три раза медленнее, чем локальной переменной.
  23. Инкремент неопределённой переменной в 9-10 раз медленнее, чем заранее инициализированной.
  24. Объявление глобальной переменной, без использования её в функции, также замедляет работу (примерно на ту же величину, что и инкремент локальной переменной). Вероятно, PHP осуществляет проверку на существование переменной.
  25. Скорость вызов метода, судя по всему, не зависит от количества методов, определённых в классе. Я добавил 10 методов в тестовый класс (до и после тестового метода), без изменения производительности.
  26. Методы в производных классах работают быстрее, чем они же, определённые в базовом классе.
  27. Вызов функции с одним параметром и пустым телом функции в среднем равняется 7-8 инкрементам локальной переменной ($localvar++). Вызов похожего метода, разумеется, около 15 инкрементов.
  28. Ваши строки, определённые при помощи ', а не ", будут интерпретироваться чуть быстрее, т.к. PHP ищет переменные внутри "..", но не '...'. Конечно, вы можете использовать это только тогда, когда в вашей строке нет переменных.
  29. Строки, разделённые запятыми, выводятся быстрее, чем строки, разделённые точкой. Примечание: это работает только с функцией echo, которая может принимать несколько строк в качестве аргументов.
  30. PHP-скрипты будут обрабатываться, как минимум, в 2-10 раз медленнее, чем статические HTML-страницы. Попробуйте использовать больше статических HTML-страниц и меньше скриптов.
  31. Ваши PHP-скрипты перекомпилируются каждый раз, если скрипты не кэшируются. Кэширование скриптов обычно увеличивает производительность на 25-100% за счёт удаления времени на компиляцию.
  32. Кэшируйте, насколько это возможно. Используйте memcached — это высокопроизводительная система кэширования объектов в памяти, которая повышает скорость динамических веб-приложений за счёт облегчения загрузки БД. Кэшированный микрокод полезен тем, что позволяет вашему скрипту не компилироваться снова для каждого запроса.
  33. При работе со строками, когда вам понадобится убедиться в том, что строка определённой длины, вы, разумеется, захотите использовать функцию strlen(). Эта функция работает очень быстро, ведь она не выполняет каких-либо вычислений, а лишь возвращает уже известную длину строки, доступную в zval-структуре (внутренняя структура C, используемая при работе с переменными в PHP). Однако потому, что strlen() — функция, она будет работать медленно за счёт вызова некоторых операций, таких как приведение строки в нижний регистр и поиска в хэш-таблице, только после которых будут выполнены основные действия функции. В некоторых случаях вы сможете ускорить свой код за счёт использования хитрости с isset().
    Было: if (strlen($foo) < 5) { echo "Foo is too short"; }
    Стало: if (!isset($foo{5})) { echo "Foo is too short"; }
    Вызов isset() быстрее, чем strlen() потому, что, в отличие от strlen(), isset() - не функция, а языковая конструкция. За счёт этого isset() не имеет практически никаких накладных расходов на определение длины строки.
  34. Инкремент или декремент переменной при помощи $i++ происходит немного медленнее, чем ++$i. Это особая специфика PHP, и не нужно таким образом модифицировать свой C и Java-код думая, что он будет работать быстрее, этого не произойдёт. ++$i будет быстрее в PHP потому, что вместо четырёх команд, как в случае с $i++, вам понадобится только три. Пост-инкремент обычно используется при создании временных переменных, которые затем увеличиваются. В то время, как пре-инкремент увеличивает значение оригинальной переменной. Это один из способов оптимизации PHP-кода в байт-код утилитой Zend Optimizer. Тем не менее, это хорошая идея, поскольку не все байткод-оптимизаторы оптимизируют это, также остаётся немало скриптов, работающих без оптимизации в байткод.
  35. Не всё должно быть ООП, часто это излишне, поскольку каждый метод и объект занимает много памяти.
  36. Не определяйте каждую структуру данных как класс, массивы бывают очень полезны
  37. Не слишком разбивайте методы. Думайте, что вы действительно будете повторно использовать.
  38. Вы всегда можете разбить код на методы позже, по необходимости.
  39. Используйте бесчисленное количество предопределённых функций.
  40. Если в вашем коде есть функции, выполняющиеся очень долго, обдумайте их написание на C в виде расширения
  41. Профилируйте свой код. Профилирование покажет вам, как много времени выполняются части вашего кода.
  42. mod_gzip — модуль Apache, который позволяет сжимать ваши данные на лету и может уменьшить объем передаваемых данных до 80%.
  43. Расширенная статья об оптимизации, автор John Lim.


Есть советы вообще к Drupal неотносящиеся (все про ООП точно), есть слишком извращенные (33 жжет Smile ), а есть полезные в любой ситуации, например 4, 5, 34 (последний, естественно, если по логике не нужен именно пост-инкремент)

В общем надеюсь, что новичкам, только начинающим писать на PHP, пригодится кое-что. А вот от опытных Drupaler'ов хочется услышать, есть ли какое-то объяснение предпочтению print перед echo? Вроде как немного, но echo быстрее должно работать, особено вкупе с использованием перечисления аргументов (","), а не конктатенации ("." - объединение строк)

Комментарии

Аватар пользователя player player 3 апреля 2008 в 13:51

Удивило

Quote:
$row['id'] в семь раз быстрее, чем $row[id].

Quote:
Инкремент неопределённой переменной в 9-10 раз медленнее, чем заранее инициализированной.

А echo сколько памяти ест по сравнению с print? Лично я (в самописных скриптах) обычно использую эхо.

Аватар пользователя KalanSPb KalanSPb 3 апреля 2008 в 14:48

Ну первое не должно удивлять, в случае $row[id] php нужно:

  • просмотреть список констант и убедиться, что там id нет
  • создать константу id
  • проинициализировать её в значение 'id'
  • подстваить ее значение
  • notice выдать Smile

Второе может не так очевидно, но наверное действительно конструкция for ($i=0;$i<100;++$i) быстрее, чем for (;$i<100;++$i), хотя бы опять notice выдать надо Smile
Да и вообще инициализировать переменные перед их использованием хорошим тоном считается в языках даже не требующих этого

памяти тоже эхо по идее должно меньше кушать, не надо возвращаемое значение инициализировать и возвращать Smile

Пожалуй единственное приемущестов print это возможность использования в конструкциях типа $i % 2 ? print 'even' : print 'odd'; а не if else городить

Аватар пользователя botan botan 3 апреля 2008 в 15:40

KalanSPb wrote:
Пожалуй единственное приемущестов print это возможность использования в конструкциях типа $i % 2 ? print 'even' : print 'odd'; а не if else городить

А ,к примеру, так echo $i % 2 ?  'even' :  'odd'; почему нельзя использовать?

Аватар пользователя neochief neochief 3 апреля 2008 в 17:19

К своему стыду, не знал про пункт 19. Во всех остальных языках это значение вычисляется всего раз в циклах типа for.

Аватар пользователя KalanSPb KalanSPb 3 апреля 2008 в 19:25

botan wrote:
KalanSPb wrote:
Пожалуй единственное приемущестов print это возможность использования в конструкциях типа $i % 2 ? print 'even' : print 'odd'; а не if else городить

А ,к примеру, так echo $i % 2 ?  'even' :  'odd'; почему нельзя использовать?

Можно, конечно. Я самый простой пример привел, наверное можно придумать что-то где факт того, что print возвращает занчение, а echo нет будет иметь значений для удобства и краткости кода

Аватар пользователя seaji seaji 3 апреля 2008 в 23:30

Мне кажется в Друпале print это устоявшееся понятие. До Друпала я и сам писал echo(), кстати одной из причин было то что это слово короче. Потом когда стал читать коды Друпал примелькалось print. Сейчас только так и пишу.
Вы знаете, это как и в любом языке, правильным считается то что чаще упоминается и чем чаще пользуются.
Вот допустим в фотографии есть понятие "эмульсионный слой" - это светочуствительный слой на фотопленке. А вы знаете что значит слово эмульсия? Это смесь двух не растворяющихся друг в друге жидкостей. Ну как масло в воде. И где здесь фото пленка? Даже рядом не лежала, однако это понятие устоялось, хоть оно и не правильно по смыслу.
Smile

Аватар пользователя KalanSPb KalanSPb 4 апреля 2008 в 0:09

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

Хотя print знакомо, наверное, каждому программисту да и хоть чуть-чуть подкованному пользователю, хотя бы по принтеру, а для англоговорящих так прямое указание "печатать", в отличии от echo корнями идущим из консоли Unix, а туда,наверное, вообще из терминалов первых. Видимо это основным соображением было.

Аватар пользователя Dan Dan 5 апреля 2008 в 21:10

По советам автора вместо
Было: if (strlen($foo) < 5) { echo "Foo is too short"; }
надо использовать
Стало: if (!isset($foo{5})) { echo 'Foo is too short'; }
а не
Стало: if (!isset($foo{5})) { echo "Foo is too short"; }

Print vs. echo
Скорее всего из-за возможности использовать внутри строки переменные:
print "Количество: $count, время: {$_SERVER[’REQUEST_TIME’]}.";
вместо
echo 'Количество: ',$count,', время: ',$_SERVER[’REQUEST_TIME’],'.';

Аватар пользователя stokito stokito 12 апреля 2008 в 20:22

Smile Эх когда я после программирования на Дельфи впервые столкнулся с веб разработкой то меня всё повергло просто в шок! Только щас оклимался когда уже вьехал. А как я офигивал от друпала видя что тут почти пофигу всем на скорость обработки.
Так что эти правила (кстати которые местами очень сомнительные) можно засунуть куда подальше. Это всё просто мелочи по сравнению с расходом ресурсов самой средой.

Аватар пользователя Wave Wave 13 апреля 2008 в 0:05

Сайт автора статьи уязвим для банальнейшей SQL-инъекции, что уж говорить о компетентности автора?
Следовательно, о самих советах.
Для новичков от них вреда больше, чем пользы.

Подробней: http://community.livejournal.com/ru_php/1205823.html
и в частности об инъекции: http://community.livejournal.com/ru_php/1205823.html?thread=16910143#t16...

Аватар пользователя Web-Rise Web-Rise 2 декабря 2012 в 12:53

Уязвимости сайта автора не могут говорить о его компетенции, возможно просто на скорую руку собрано и оставлены на потом какие-либо моменты.

Аватар пользователя player player 13 апреля 2008 в 13:19

Quote:
:-) Эх когда я после программирования на Дельфи впервые столкнулся с веб разработкой то меня всё повергло просто в шок!
Когджа повстречался с дельфи, то был просто шокирован его скоростью после c++

Аватар пользователя beerman beerman 4 ноября 2008 в 11:43

вспомнилось:
в былые времена программеры из РТСБ пытались нам, колхозным писакам, доказать преимущества FOX'a перед CLIPPER'ом.
Простая демонстрация поиска товара в базе из более чем 30 000 записей расставила все точки над "йо".
А еще мы обновления этих баз тащили мопедами на 2400MNP5.

ЗЫ. "Когда дискеты были большие..."