Частые ошибки и нерациональные решения в php коде
Ниже описаны наиболее часто встречающиеся в php коде ошибки и нерациональные решения. Многие из них не критичны или, по крайней мере, таковыми кажутся, но при определенных условиях могут серьезно замедлить выполнение скрипта.
-
for ($i=0; $i < count($ar); $i++) {...}
в этом случае функция count будет вызываться при каждом проходе цикла.
Вспомним (или узнаем) как работает for:
for (expr1; expr2; expr3) {...}
expr1 - выполняется 1 раз до начала цикла;
expr2 - выполняется до начала каждой итерации;
expr3 - выполняется после каждой итерации.
Зная это мы можем запросто избежать предыдущей ситуации. И еще много чего можем. Например, надо пройти по массиву
$arr = [1, 'a', 2, 'b', 3, 'c', 4, 'd'];,
и прерваться, если значение элемента будет равно 3, при этом сообщить сколько итераций было совершено. Стандартное неоптимальное решение:$counter = 0; for ($i=0; $i < count($ar); $i++) { if ($arr[$i] == 3) { break; } echo $arr[$i]; $counter++; } echo $counter;Короткое:for ($i=0, $counter=0, $size=count($arr); $i < $size, $arr[$i] != 3; ++$i, ++$counter) { echo $arr[$i]; } echo $counter;
-
preg_match('/a-zA-Z/i', $subject)
зачем здесь две группы символов? Одну из них, a-z или A-Z, можно убрать, подумайте почему...
А вот с символами кириллицы лучше именно так
preg_match('/а-яА-ЯёЁ/', $subject)
(да, ещё и "Ё" отдельно, т.к. она не входит в диапазон), потому что при корявой настройке локали на сервере php не различает строчные и прописные русские буквы, а при явном указании /а-яА-Я/ мы задаем диапазон кодов символов, поэтому функция будет работать как и ожидается (из-за локали также могут не работать с кириллицей функции strtolower и strtoupper)
-
"Cannot send session cookie — headers already sent by… " — попытка установить куки, когда
заголовок уже послан браузеру — не заметили пустую строку или пробел в начале файла
- Разнесение подключаемых с помощью require_once функций на множество мелких файлов не оправдано
— php гораздо быстрее подключает один большой
-
echo "something $var something";- медленно
гораздо быстрее:echo 'something '.$var.' something';
еще быстрее:echo 'something ',$var,' something';
-
if (mysql_query("select * from users where login='login' and pass='pass'", $db)) {
$auth = true;
...
}
если запрос корректен, то он вернет true даже если ни одной строки не было выбрано. В подобных случаях нужно использовать mysql_num_rows
-
function len($str) { return strlen($str); }
переписывание стандартных функций языка - зачем?
-
Для чтения файла file() быстрее, чем fopen + цикл
-
Разработка велась под windows, а хостинг на linux и сайт не поднимается —
имя файла index.php, Index.php, INDEX.php и т.д. это все разные файлы для linux систем
-
Залив проект на хостинг, отключите вывод ошибок на экран — логируйте их в файл,
будет меньше неприятных ситуаций потом
-
PHP файлы с нестандартными расширениями (к примеру, .inc вместо .php) —
если не защитить такие файлы, а лучше вообще их избегать
-
Реализация функционала БД средствами PHP — array_search вместо
WHERE и другие чудеса незнания SQL, тут без комментариев
UPDATE: почему стоит "ловить микросекунды"?
Ответ прост: грубо, если на вашем сайте 1000 посетителей, то выгрыш в 1 миллисекунду в скрипте может дать вам до 1 с выгрыша при загрузке страницы. Что дает снижение скорости загрузки страницы на 1 с можете почитать здесь.
Рассмотрим вкратце аргументы кулхацкеров против подобной оптимизации:
- "ну выграю я 1 мс, ну и что это даст..." - читаем выше
- "сейчас железо настолько дешёвое, что всегда можно добавить еще один сервак и не париться..." - во-первых, какое бы дешёвое не было, зачем тратить деньги, когда можно и не тратить; во-вторых, чаще всего с ростом посещаемости нагрузка на сервер растет нелинейно, так что в следующий раз придется добавлять уже 2,4,8...
- "это все херня...", "вы все быдлокодеры..." и т.п. - а писать такие комментарии это прям важное дело? Не тратьте время, проходите мимо.
Вывод: если пишите сайт для себя и поисковых роботов, то "ловить микросекунды" действительно не стоит, если и для других людей, то можно, как минимум, задуматься над этим. Ну и фанатеть по оптимизации, конечно, тоже не нужно, т.е. если для выгрыша N мс придется переписать функцию из 10 строк в 100, то тут, пожалуй, можно сделать выбор в пользу читаемости.
Про debug ошибок
Оценивать производительность и проводить оптимизацию стоит как минимум на том же наборе ПО (ОС, версия HTTP сервера, версия и сборка php), что и на продакшене, а в идеале на таком же железе. Дело в том, что время выполнения одного и того же скрипта может различаться между linux и windows в десятки раз (!), а на различных сборках ПО - до нескольких раз. Почему "может"? Потому что это зависит от состава скрипта, например PCRE функции (preg_replace, preg_match и т.д.) под виндовсом серьезно медленнее.
Быть добру!
Зачастую для ускорения работы ф-ии люди передают в нее ссылку на тот или иной элемент.
Хочу сказать что это не оправдано так как php подерживает механизи "отложенного копирования" что означает что на самом деле и так передастся ссылка на элемент а не его копия.
(Я думаю сложно будет сейчас уже найти хост где используют настолько старый php где у него нет этого механихма)
Вывод: используйте передачу по ссылке если в ф-ии вам и вправду нужно будет изменить элемент.
С третьим не соглашусь. Часто бывают случаи что маленькими файлами подключаются разные функции, которые временами в целях отладки должны быть выключены. Проще закомментировать строку require_once чем комментить кусок кода в большом файле.
php подключает один большой файл БЫСТРЕЕ, чем много мелких несмотря на то, что где удобней комментировать
Автор, ты не объяснил почти ни один их пунктов!
И вообще такое впечатление, что ты быдлокодер дошкольного возраста...
Вир, да, в школу я только на будущий год пойду. а вот если тебе для данных примеров требуются объяснения, то кто из нас "быдлокодер" это еще вопрос...
"php подключает один большой файл БЫСТРЕЕ" - наверное потому что web-сервер быстрее читает из одного файла, а не из многих? ;)
Автор, спасибо за сайт. Некоторые статьи нашел для себя очень полезными.
Такой вопрос(совет) - почему Вы не используете htmlspecialchars() при сохранении комментариев? У Вас же вот такие знаки " < ' экранируются слэшами, да с ними и выводятся.. А с упомянутой функцией специальные символы преобразуются в HTML сущности и будет красиво..
Ой, оказывается используете.. Ну stripslashes тогда надо делать :)
Вот немного, так на вскидкУУУУ :)
функции как echo медленней чем принт.
print "tralala {$value}"; //самое медленное
print "tralala $value";
print 'tralala '.$value;
Лучше писать все в одном файле. Особо здоровые куски, можно инклюдить. формы, и т.д.
сложнее для взлома, и наибыстрейшие время выполнения.
Правдо вот что-то менять в таком коде сможете только Вы :)
PS: для соеденения ключиков, запятыми, можно использовать
implode(',',$keys) вместо цикла for по массиву с ключиками.
Используйте включения, когда это возможно:
$a = <<< BUF
<html>
...
</html>
BUF;
вместо:
$a = "<html>
...
</html>";
modder from moddi.ru, сложно понять, какого именно мнения вы поддерживаетесь,- синтаксис и пунктуация есть в таком языке, как русский.
..и такой вопросик, давно интересовавший:
Какой вид кавычек "быстрее" " или ', сам я думаю что ', т.к. транслятор "не будет искать" в таких строках ссылки на переменные... как думаете вы?
одинарные кавычки быстрее, именно по указанной причине
По поводу ошибок. Грабли, на которые наступил давно - это четыре оператора подключения файла: include, require, include_once и require_once, соответственно. Создав файлик с функциями, принялся радостно подключать его include( 'file.php' ) везде, где это было необходимо. А так как некоторые файлы при работе подключали и 'file.php', и другие файлы, которые, в свою очередь, также подключали 'file.php', то итог был печален: множественное определение функций, возникшее из-за множественного включения. После этого последовало внимательное изучение документации.
Ваша экономия наносекунд превращает код в нечитаемый низкоуровневый говнокод.
мне кажется те, кто так ругается, просто узнали в статье свой "стиль программирования" ...
тем кто ругается видимо больше нечего сказать... жаба давит что умный человек знаниями поделился...
Согласен насчет наносекунд :-)
А, вообще, автору респект за попытку и в аццтой всех гневнокритиков.
Действительно, есть ведь такие понятие как MVС, использование тех или иных фреймворков, ORM... вероятно подобный подход к архитекруте ИС менее производителен чем вылизанный, с точки зрения приведенных выше советов, скрипт... но читается и поддерживается в разы хуже... сейчас уже наступило то время, когда дешевле добавить еще один сервер в кластер, чем вылизывать код... разумеется всему есть предел :)
Я жую, и пока жую, почитываю разное: вдруг какие-то идеи интересные подвернутся. Комент Dekoo меня рассмешил. Фреймворки придуманы для того, чтобы дети не ломали себе голову над трудностями программирования. Но если б не дяди, которые создают различные библиотеки функций и ВЫЛИЗЫВАЮТ КОД, детям пришлось бы туго. Так что, каждому свое - кто-то создает технологии, а кто-то способен только на использование чужего. Подход "добавить еще один сервер в кластер" и сгребание кода с помощью бульдозера - это метод лентяев и бездарей.
Константин, вы смешите еще больше.
"Фреймворки придуманы для того, чтобы..", "дяди", "дети" :\ лол
"Так что, каждому свое - кто-то создает технологии, а кто-то способен только на использование чужого.", - c такой философией, почему бы вам не придумать свой PHP и использовать его? зачем использовать готовый велосипед, соберите свой!
Подход "добавить еще один сервер в кластер" - это не метод лентяев, это рациональное решение, т.к. хороший программист стоит в разы дороже, чем хорошая железка.
to Автор: Неплохо было бы указать про "ловушки" cookie, а также совет не увлекаться процедурщиной и изучать ООП
"kolpeex 30.06.09 19:32
Ваша экономия наносекунд превращает код в нечитаемый низкоуровневый говнокод."
категорически не согласен. из наносекунд порой собираются секунды и минуты.
а код нужен не для чтения, а для выполнения сервером. между прочим, все грамотные хостеры ставят ограничения на процессорное время, память и прочие небесконечные характеристики своих машин. да если у вас и свой dedicated - на пиках посещаемости такие ошибки могут сыграть свою роль. вот и думайте, что лучше.
вот еще забыл добавить насчет читаемости: наберите что угодно в google и откройте исходный код странички. или, может, google вы тоже не уважаете?
гугл используют сжатие исходного кода. Если скопировать исходники гугл и отфомратировать в любой ide, получится вполне читаемый код
Отличный сайт! Очень много всего интересного и полезного что использую на практике.
Насчёт "слишком длинные имена переменных (8 и более символов) снижают быстродействие (не могу точно объяснить почему, но это факт)"
Это связано с отводимым колличеством байт на хранение имени переменной. Это место дискретно увеличивается: 8, 16, 32.. Получается, если использовать имя переменной до 8 символов, то их прочитать и работать с ними быстрее, чем с 16 или же с 32. Всё дело в адресации памяти:)
- Использование ООП там, где это не нужно (классы замедляют работу, используют больше памяти);
- Ресурсоемкое преобразование данных, полученных из БД, при выводе (лучше преобразовывать в нужный для вывода формат при добавлении, поверьте, добавляют что-то значительно реже, чем просматривают, это снизит нагрузку);
- То, что обновляется примерно раз в час/день/месяц, например статистика за день, лучше кешировать (чтение из файла быстрее, чем из бд);
- Не используйте шаблонизаторы, дополнительные библиотеки без их надобности;
Немного не по теме: иногда, если вылетает ошибка, нужно найти ей объяснение в гугле. Чаще выдает не страницы с форумов о PHP, а как раз страницы, где эта ошибка вылетает и уже проиндексировалась:).
За год изучения пхп ни разу не спрашивал ничего на форумах, всё уже написано и объяснено, за что спасибо людям делающим подобные ресурсы.
Спасибо, хорошая статья.
Поделюсь и я - над чем проломал голову около суток, Пусть другие не попадут.
Есть у меня куча функций для разбора объявлений по частям:
начал разбирать, какую часть можно оптимизировать, чтоб быстрее было
Никак не хотела одна из функций сокращаться во времени. Если весь цикл занимал 5 секунд, то 4 из них занимала эта функция.
Я все мозги себе слоамал, пока нашёл причину.
Не заметил, что внутри подгружённой require'ом функции есть ещё одна вставочка include. А теперь представьте каково это загружать полторы тысячи раз один и тот же файл. :)
И второе. Про SELECT тут уже сказано. А вот то что оказывается и UPDATE ! выдаёт true в любых ситуациях, когда запрос составлен верно. Т.е. даже если ни одного изменения сделано не было! Вот эта заковыка украла у меня добрые сутки времени.
Правда я использую mysql_affected_rows(). Только проблема в том, что она работает только при подключенном к базе состоянии. У кого-нибудь есть иное решение?
Крикуны "быдлокодер" и т.п. не заслуживают право находиться в обществе образованных людей. Идите в ассенизаторы, мир будет чище и приятнее. Альтернатива - убейтесь об стену, если не умеете культурно излагать свои соображения.
Про "купить сервер", "вылизать код" - код должен быть грамотно составлен с учетом расхода памяти и процессорного времени. Лишние траты того или иного делают код некачественным, а следовательно программиста не "хорошим" (как сказали выше, сравнивая стоимость программиста с сервером).
Сомневаюсь, что кто-то будет покупать вертолет только из-за того, что не может додуматься поехать коротким путем на автомобиле.
Вот из этого:
echo "something $var something";... - медленно
гораздо быстрее: echo 'something '.$var.' something';
еще быстрее: echo 'something ',$var,' something';
Знал только два первых способа, но не знал что они различаются по скорости!! Огромное спасибо за третий способ, проверил - работает.. Очень рад!!!
Еще такой вопрос - написали что
"tralala {$value}"; - самое медленное!
Но здесь по сути можно и не писать фигурных скобок!! Вот если бы так было - "tralala {$value[3]}"; тогда надо, либо вот так лучше - 'tralala ',$value[3],''; Сам вопрос же заключается в чем!! Как тогда в запросе mysql - записать вот это $x[3] без фигурных скобок (чтобы было быстрей)?? Если так mysql_query("SELECT ... `...` = '",$x[3],"' или '".$x[3]."' или = '.$x[3].' или ''.$x[3].'' ") не работает! Спасибо еще раз!!!
>> "Ваша экономия наносекунд превращает код в нечитаемый низкоуровневый говнокод."
Полностью согласен.
Хочу еще добавить - друзья программисты, оставляйте комментарии и придерживайтесь одного стиля написания кода и желательно "стандартизированного".
Нано-секунды ЗАВИСЯТ от скорости винта на серваке, а проц-время это было потом. :)
Бычи-код, Быдло-код, !!!
Вопрос в том насколько сложен проект, ШОБ экономить и оптимизировать, ДАА, а вот если три клика в месяц, тут надо постараться с оптимизацией.
Автору СПАСИБО, написать статью Сложнее нежели кинуть короткий комент, причем не обоснованный.
Google наплевать на ВСЕ саты.Google собирает информацию, вне зависимости от БЫЧЕ !!!
if(mysql_query("select * from users where login='login' and pass='pass'",$db))
$auth = true; ...
если запрос корректен, то он вернет true даже если ни одной строки не было выбрано. В подобных случаях нужно использовать mysql_num_rows
====================================
лучше ипользовать mysql_query("select count(*) .... "),
а еще лучше не использовать mysql_query, а PDO
чем лучше то?
anonymous, плейсхолдерами лучше