Как стать автором
Обновить

Комментарии 301

Сразу бросилось в глаза. Не count() алиас, а как раз наоборот — sizeof() есть алиас для count():
ru2.php.net/sizeof
Спасибо, поправлю, переставил места в уме.

time php -r 'for ($a=0; $a<10000; $a++) count($_SERVER);'
php -r 'for ($a=0; $a<10000; $a++) count($_SERVER);' 0,04s user 0,01s system 90% cpu 0,055 total


time php -r 'for ($a=0; $a<10000; $a++) sizeof($_SERVER);'
php -r 'for ($a=0; $a<10000; $a++) sizeof($_SERVER);' 0,03s user 0,02s system 82% cpu 0,061 total
Это отсюда следует вывод
sizeof() это синоним count(), работает быстрее

?
Ну-ну…
Аааа, бросилось в глаза.
Nobody cares ваще-то
НЛО прилетело и опубликовало эту надпись здесь
Не знаю, поддомен автоматом подставляется, я пишу просто «php.net/{function_name}», когда обращаюсь к мануалу.
Оптимизаторы, блин. Ну нет смысла гоняться за милисекундами, ясно ведь что это ничего реального не даст. А если будут реально мощные наргрузочки — по-любому придется масштабировать проект, далеко на профилировании PHP-кода с его последующей оптимизацией не уедешь.

Вот вераня мысль на эту тему, полностью согласен с Котеровым:

forum.dklab.ru/viewtopic.php?p=42214#42214
Например, 30 000 000 хитов в сутки * лишние 50-100 миллисекунд, это уже сотни часов серверного времени. Которые стоят денег.
И эти сэкономленные часы, могут отложить необходимость «железного» масштабирования, на месяц, может быть два.
Если вы бутстраппер, и стараетесь минимизировать расходы, это может сыграть свою роль.

Да и вообще, политики «тормозит — смени железо» и «главное — скорость разработки», приводит к тому, что в моей кубунте, питоньих скриптов скоро будет больше чем бинарников. Ничего против питона не имею, но реально — уже заметно тормозит.
Кстати, в данном случае, не Котерова надо цитировать, а Дональда Кнута, он всё-таки был раньше.
Что значит «стоят денег»? Хостер что ли подсчитывает время и выставляет чек? Нет. Пример с кубунтой кстати совсем другого рода. Раз тормозит, значит есть смысл подумать об оптмизации. Именно в таком порядке!

А Кнут вообще-то программист несколько другого рода. У нас же веб, тут свои законы и принципы.

Если о цитатах, то вот ещё можно взять книгу Фаулера «Рефакторинг». Там он разбирает рефакторит пример кода и при этом намеренно допускает ухудшение его производительности. Разбивает один цикл на два, каждый из которых с тем же количеством итераций. И дает насчет этого достаточно подробный и внятный комментарий.
«У нас же веб, тут свои законы и принципы.»

Мы кажется диаметрально противоположны во мнениях.
В вебе, скорость загрузки, прямо влияет на продажи/регистрации/заказы.

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

Стоит денег, потому что секунды собираются в минуты, минуты в часы, и приходится увеличивать количество серверов.

По поводу Фаулера, ничто не мешает писать и быстро и понятно =)
В вебе, скорость загрузки, прямо влияет на продажи/регистрации/заказы.


Для десктопных приложений характерно наличие тяжеловесных ресурсоемких и долговыполняющихся операций. И в этом случае разница между оптимизированным и неоптимизированным кодом будет выражаться в минутах — что для юзера ощутимо. В вебе такого обычно не бывает. Отправил запрос — получил ответ. И тут разница выражается в долях секунды — конечному пользователю до них по-барабану.
Далеко не по барабану.
webo.in/articles/habrahabr/54-psychology-web-performance/

У нас всё-таки всё очень разное, и десктопы и минуты, думаю, мы не убедим друг друга ни в чём =)
Если конечно всё не настолько плохо что страница после 30 секунд полной тишины вылетает с таймаутом, бывает такое на перегруженных сайтах, и честно говорю раздражает куда больше чем если бы она открывалась 60 секунд, но открывалась бы рано или поздно…

Но это касается развлекательных сайтов, если интернет магазин, проявляет признаки «тормозов» я незамедлительно иду в другой магазин.
(При покупке той или иной вещи, мне нужно быстро ознакомиться с вариантами. Ждать по 3-5 секунд каждую страницу, это отвратительно. Тем более что иногда информация о нужном товаре в 3-5 кликах, а если товаров ещё и несколько… Ужас короче.)
Пока программисты думают вот так:
А Кнут вообще-то программист несколько другого рода. У нас же веб, тут свои законы и принципы.

В вебе останется куча жуткого говнокода, за который надо расстреливать.
Да, и нормальным PHP-шникам, придётся продолжать объяснять, что они не быдлокодеры, и ничем не хуже других.
Как я вас понимаю.
Для многих PHP равняется быдлокодерству, это печальная правда.
Ноги растут из того факта, что какой-нибудь вчера-прочитал-два-туториала-рубист, поискав работу пару месяцев, резко осознает, что не смотря на то, что он высшее существо, с синтаксическим диабетом, почему-то всем нужны быдло-PHP-шники.
(далеко ходить не надо, я сам вчера вакансию (Казань) опубликовал)
И у него начинается производство кирпичей.

Не холивара ради, но радует, что школота уже не считает PHP крутым, и идёт на более домохозяечные языки.
В вебе останется куча жуткого говнокода, за который надо расстреливать.


А нифига

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


ru.wikipedia.org/wiki/%D0%98%D1%81%D0%BA%D1%83%D1%81%D1%81%D1%82%D0%B2%D0%BE_%D0%BF%D1%80%D0%BE%D0%B3%D1%80%D0%B0%D0%BC%D0%BC%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F
В вебе нет привязкии к архитектуре?
А есть?
Вопрос немного странный, если веб работает на C++, через CGI, то вообще-то привязка будет.
Или вы что имели ввиду?
Ну пока у вас десять посетителей в сутки, то никакой привязки конечно нет. А если у вас hi-load, то у вас постепенно и особенности PHP в ход начинают идти, и ORM улетает в небытие, а потом вдруг у вас форкнутый MySQL и собственный компилятор PHP.

Просто большинству вебо-быдло-кодеров никогда не работать с такими проектами, как Facebook, от того и отношение такое. Это на малых проектах вы можете себе позволить докупать по серверу в месяц, а когда вам приходится покупать по сотне серверов в месяц, то каждая микросекунда приносит кучу сэкономленного бабла.

Справедливости ради стоит отметить, что замена двойных кавычек всё-равно ничего не даст (:
Я примерно это и пытался донести, по поводу микросекунд и серверов.
Бля! Да вы сначала добейтесь такого кол-ва хитов, а потом говорите о производительности. Посещаемость сайтов обычно увеличивается экспоненциально. И оптимизировать вы станете не такие мелочи, а реально узкие места.

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

«Да вы сначала добейтесь такого кол-ва хитов, а потом говорите о производительности.»
Я не вчера пришёл в профессию, и, опыты были разные, и 30 000 000 qpd, это всего лишь 40 qps.
PHP, кстати, это не только сайты. Это, например, фронтенды систем сбора информации.

«Посещаемость сайтов обычно увеличивается экспоненциально.»
Ваш вывод основан на каких данных, с каких сайтов?

«хитрых конструкций»
Какая именно конструкция вам кажется хитрой? Я могу разъяснить.

«для мнимого увеличения»
Можете замерить для своего кода, поделиться с нами, это будет конструктивнее, нежели голословные обвинения в мнимости.

«не давая никаких плюсов на 99% сайтов»
99% сайтов, не поднимаются выше 100 хостов в сутки, конечно же, эффект будет не заметен.

Вас что разозлило до состояния «Бля!»?
Просто люди и задачи бывают разные:
— те люди, которым посчастливилось запустить проект с огромной посещаемостью, как правило, уже познакомились с основами оптимизации и ваша статья не дала ничего нового;
— молодые разработчики, которые только начали свое вхождение в веб-разработку, обычно не делают ничего крупномасштабного: как правило это разработка всевозможных сайтов-визиток, промиков, и пр. «новости-статьи-фотогалерея-с-пхпББ-форумом». Посещаемость на таких проектах как правило крайне мала (ура! сегодня приходил яндекс-бот), тонкая оптимизация их не интересует, работы и так много — надо срочно дописать свою ЦМС. Часть из них что-то усвоит и скажет вам спасибо, остальные хабр возможно и не читают :)
— студенты-нерды: зазубрят каждую сторчку вашей статьи и будут «оптимизировать» где только можно и нельзя в своих лабораторных работах (не забыв заменить все двойные кавычки на одинарные!). Такие люди имеют шанс впоследствии стать неплохими специалистами, когда со временем придет опыт и юношеский пыл поутихнет (если не увлекутся чем-нибудь еще и не уйдут в другую отрасль).

Вывод: в первом случае цена железа может оказаться меньше стоимости оптимизации, во-втором случае оптимизация обычно не проводится (даже если нужна), в третьем нужна оптимизация или не нужна — не важно, она там будет, ибо fun.
Надеюсь, никто не будет зубрить мою статью.

Оптимизация, может быть не отдельным процессом, а больше стилем, вот я о чём.
Если вы про то, чтобы научить себя сразу писать оптимально и красиво, то да, это хороший стиль!
Именно про это, в противовес подходу «пойду-ка напишу скрипт для замены всех count и sizeof».
Что в вашем понимании «стиль» применимо к оптимизации? Писать «simplexml_load_string( file_get_contents ('file.xml') )» вместо «simplexml_load_file('file.xml')»? Без дополнительного комментария рядом это — WTF.

Поймите: единственно верной статьей по оптимизации PHP может быть описание как пользоваться профайлером и описание где искать информацию по оптимизации базы и кеширования.
Единственно верным и надежным способом является набить всем шишки самому.
Но люди, зачем-то обмениваются знаниями и наблюдениями.
«фронтенды для сбора информации» чаще всего вообще-то переписывают на С++ :)
Я не про высоконагруженные сенсоры, а про проекты попроще, где важна универсальность и удобство PHP.
НЛО прилетело и опубликовало эту надпись здесь
Делать код быстрее имхо лучше чем делать «как знают все». Тыделаешь сайт для посетителей или для разработчиков?
Почитайте что-нить нормально по оптимизации (например: habrahabr.ru/blogs/php/22881/) и не пишите чушь.
По книжке конечно жить хорошо, но опечатки могут тебя подвести.
В серьезных проектах уже не действуют те законы оптимизации, которые можно применять к стандартным студенческим сайтам. К примеру проектирование базы данных — кардинально отличается… — как пример запросы на обычном не нагруженном сайте могут выглядеть как связка 2 -х 3-х и более таблиц, что довольно часто недопустимо на мега-проектах (я бы сказал веб системах) — там это может делаться в 2-3 отдельных запроса.
Типичный пример — эта статья — поверь, человек не просто дурью маялся. И иногда посидеть часок-другой над таким рефакторингом намного выгоднее чем платить лишнюю тысячу долларов на новый процессор или сервер.
Закон оптимизации только один — профайлинг. Других нету. Действует везде.
Профайлинг приложения в целом, а не искусственного кода на однопользовательской машине.

Человек именно что маялся дурью.
Тe самые запросы выполняются в миллионы раз дольше, чем высиженная здесь мифическая разница между count и sizeof. Весь этот «рефакторинг» высосан из пальца. И оптимизировать надо их, а не это фуфло.

Рефакторинг, my ass. Вот ты аффтару подсуропил. Он-то пытается сейчас закосить под девочку, выставить свои поучения как ни к чему не обязывающие советы, типа «Ну если все равно какую функцию использовать, то лучше „более быструю“. На этапе разработки, разумеется. Но даже он и в кошмарном сне себе не представит, что по его статье надо срочно садиться и перепахивать весь код на использование „более быстрых функций“.

Продолжай его защищать. С такими друзьями врагов не надо :)
Я не хочу с вами спорить, т к закон законом, но дело не в том. Это не подмена законов и т д, это дополнительные возможности сэкономить на железе, времени и деньгах.
Если вы исключаете для себя еще одну возможность ускорить свой код — продолжайте ограничивать себя дальше.
В то-то и дело, что нет тут никаких дополнительных возможностей.
Даже автор уже изъюлился весь — «летают, но нызенько-нызенько! На разных осях/сборках/машинах все будет по-разному!!» Ну и толку-то тогда в этих советах, если у соседа они приведут не к экономии, а к расходам?
На самом деле — бред, конечно. Ни к экономии, ни к расходам этот набор заклинаний не имеет никакого отношения.
Дело не в том, какая функция быстрее или медленнее. А в том, что эта разница не влияет на конечный результат. Ключевое слово — конечный результат. На конечном результате мы получим неразличимую разницу — в пределах погрешности.
Это очень сложно понять тому, кто ни разу не пользовался профайлингом и не научился отличать значимое от незначительного. Но рекомендую хотя бы попытаться.
Ты клёвый, ты столько про меня знаешь, я уже привязался к тебе =)
сами то не юлите? Туда сюда, конечный результат… Профайлинг — профайлингом. Писать то надо уметь, чтобы понять почему что-то тормозит.
Тупо отрицать то что работает. И если ты немного подумаешь, а не будешь прикрываться законами, то может поймешь, что можно применять и в большинстве случаев успешно.
Не как основное, а как дополнение.
Конечно можно орать что лучше когда сразу через хDebug все прогнать.
Есть куча возможностей по ускорению проекта на других уровнях (redis, memcached, memory tables, ssi, nginx) — но никто же из-за этого не отменяет оптимизацию.
Не будь ограниченным, бо из-за таких рамок можно пропустить очевидные вещи, которые могут ускорить проект.
ну нашёл ты узкое место, а дальше что? а дальше открываем подобную статью и смотрим что в этом узком месте можно соптимизировать.
Нет-нет! ни в коем случае!
Здесь это не работает.
Вот и автор даже сам уже сто раз повторил, что на других системах все будет по-другому (какой тогда вообще смысл было писать — это другой вопрос). То есть, он сам же и пишет, что НЕ НАДО обращаться к его статье.

Оптимизация — это процесс. Её нельзя просто «добавить». В каждом конкретном случае надо действовать по-разному.
Хороший пример — база данных.
Плохая статья напишет «добавь индекс на поле, по которому идет поиск». Хорошая — «изучай эксплейны для твоего КОНКРЕТНОГО случая». Это не всегда занимает 5 минут. Но это то, что реально помогает, и то, что приходится делать.

Но вообще, конечно, это все пустое. Подавляющее большинство комментаторов никогда в жизни не столкнутся с необходимостью опртимизации, а столкнувшись — будут решать ее совсем другими средствами. Не зря на форумах так много вопросов «какая самая ыбыстрая CMS»
без статьи я бы и не узнал, что file_get_contents может быть быстрее file. как бы я об этом узнал читая эксплейны? или предложишь открывать исходники этих функций?
Она не быстрее.
Найди слово рефакторинг в моей статье, потом с удовольствием выслушаю извинения, и рассуждения о «высосанности из пальца».
Что вам, что автору сего топика советую прочитать Макконнелла «Совершенный код», раздел про оптимизацию. Там очень хорошо показано почему рулит профайлинг живого кода и почему никогда не следуют делать синтетические тесты для попыток что-то там померить.
Цитату из топика приведу:

«Замечу, что многое зависит от вашей архитектуры, и практически любой совет надо проверять на своём коде, не доверяя полностью чужому опыту.»
Тогда еще раз повторю: единственно верной статьей по оптимизации PHP может быть описание как пользоваться профайлером и описание где искать информацию по оптимизации базы и кеширования.

Раз приходится делать подобные микро-оптимизации, у вас узкое место — PHP. Смените язык и не страдайте фигней. Много кода, слишком долог будет перенос на другую технологию? Ок, напишите модуль к PHP на С.

Та же самая Java, если ее знать, ничуть не медленнее для разработки сайтов, а вот в плане отладки и скорости выполнения обгоняет PHP на *порядки*.

Вы работаете с языком очень высокого уровня. Основные оптимизации — алгоритмы, архитектура, смена языка. Микро-оптимизации не принесут достаточного эффекта, чтобы о них даже задумываться.
Кстати, как раз уже неделю, изучаю JSP + Tomcat, java поражает скоростью, хотя пока непривычно.
LOL
как я и говорил — аффтар тобой недоволен. Найди, говорит, слово «рефакторинг» в моей статье и извинись!
лизать-то тоже надо с умом, хе-хе
Я выражаю свои мысли (не всегда совпадающие с автором), которые доказал.
Отгадай такую задачку:
У тебя есть 5 спичек. Как сложить из них 4 треугольника так чтобы они не пересекались?
(Ответ — посмотри на них в трехмерном пространстве тогда помешь как это сделать)
Вывод:
Если ты смотришь на проблему в одной плоскости — успехов.
пардон, конечно, но чтобы выиграть на нагруженном проекте 100мс путём таких оптимизаций — нужно чтобы код был совсем уж лапшой.
Очень просто, к примеру strtr в некоторых случаях (короткие аргументы), оказывается быстрее группы str_replace.

Как вы думаете, средний шаблонизатор, сколько делает замен за запрос?
1. Я комментировал статью, не надо придумывать на ходу другие примеры. Я прекрасно знаю, как ещё можно оптимизировать код. Я лишь уточнил, что примерами из статьи вряд ли удастся оптимизировать проект, который работает на 40rps (пускай загрузка будет равномерной). Итого — по 25мс на запрос. Т.е. оптимизировав код на 100мс, вы получится время выполнения (барабанная дробь) = -75мс. А теперь ещё добавим неравномерную загрузку и получим ещё более обескураживающие результаты

2. Если strtr в некоторых случаях и выигрывает, то, логично предположить, что в некоторых — проигрывает. Как вы будете производить выборку рантайм и какова будет итоговая маржа — тоже стоит лишь гадать. И на вашем месте про 100мс на указанных нагрузках я бы таки не вспоминал.
ps: я вам поверил, а вы ошиблись — 30M rpd == 347.(2) rps, т.е. 2.88ms на запрос. Где вы тут оптимизируете на 100мс — ума не приложу.
Да, насчёт 40qps, я ошибся, это нагрузка у текущего проекта, сорри.

Число 100 было выбрано без задней мысли. Знаете, некоторые люди, называют хайлоудом проекты, у которых 2400ms на страницу.

Ситуация сильно меняется, если это выигрыш 10ms?
Если не ошибаюсь, там получается выигрыш в несколько сотен часов, и сути дела это не меняет.
Суть дела меняет.

2.4s на запрос (забудем о нюансах) — это максимум 36rpd
2.39s на запрос — это максимум ~36151rpd

Для меня эта разница не принципиальна. А для вас? Ах, да — указанные 30М хитов проект с такой производительностью наберёт за 833.(3) дня. Т.е. за 2.28года. Выигрыш в 83.(3) часа (3 суток) за более чем 2 года — это насмешка над командой оптимизаторов.
Извините, я немного не понял, как 36rpd из 2.4s получилось.

Это 36 requests per day?
36k, забыл суффикс. Это ведь очевидно. По вычислениям, кроме опечатки, есть претензии? :-)
Нет, это не претензия, я просто не понял =)

По поводу вычислений, соглашусь, но вам не кажется, что еще важна площадь кода?

И да, для меня это критично, чисто из перфекционизма, наверное. =)
Я не против вашего подхода — я сам пользуюсь (исторически и интуитивно) почти всеми техниками, что и вы описали — мне просто не совсем понятен подобный подход к изложению. Лично я считаю, что новички сами должны до этого всего дойти, наступив на сотни граблей. В конце-то концов, у начинающих программистов нет таких нагрузок, где подобные спичечные оптимизации были бы эффективны, а для неначинающих вы Америку и не открыли…

Хотя я уже придираюсь, скорее, согласен )
Во, понял что я хотел сказать, но никак не мог: ваши советы стоит преподносить как best practices, но не как руководство к действию при оптимизациях скорострельности.
Ну, теперь всё ясно, мир? =)
Мир, да. Я сам к этому выводу пришёл только сейчас. Если с него и начинать — много времени бы сэкономили :-)
bullshit это называется, а не best practices
обычные нубские рассуждения на тему «прирост в 5-10 раз!!!».
Что бы он ни лепетал в оправдание, но в головах у «джуниоров» оптимизация все равно останется не процессом, а набором цитат Мао. заменил инклюд_онс на инклюд — и порядок. ПОДХОД неверный в принципе.
О банальных вещах, вроде «одинарные кавычки вместо двойных», думаю, знают все, my ass. После этой фразы УЖЕ можно дальше не читать, все и так ясно. Че-то ты тормозишь. Не расшаркиваться надо, а запинать и поставить на место. Карму бережешь? нуну.
Могу нахуй послать, чтоб не было подозрений в кармадрочерстве, успокоит?
Нубские, наверное, даже будучи php-кодером 7-ой год, я рад, что мне есть куда расти, и чему учиться.

Кстати, попробуй переспать с живой женщиной, ну хотя бы с платной.
Это снимет болезненные приступы немотивированной аггрессии к незнакомым тебе людям. С правой рукой ты такого не добьешься, я гарантирую это =)
Чувак сливается сплошь и рядом.
habrahabr.ru/blogs/php/102598/#comment_3188263
«летают, но нызенько-нызенько»

Фееричное, в соскдних предложениях:
1) «Даже на Debian и Ubuntu, PHP иногда ведёт себя по разному».
2) «Тут просто список особенностей поведения.»
Фигли писать список особенностей (зачем он вообще нужен — другой вопрос), если сам же тут же говоришь, на разных системах особенности даже не воспроизводятся.

Тут не сюсюкать надо. Тут за шкирку и в кучу носом натыкать.
Неделя свободы осталась, понимаю Вас, беснуйтесь дальше.

1. Да, это распространённое явление, мейнтенеры могут иметь разные взгляды на параметры сборки.
2. Я указал список систем, которые наблюдал, и отметил, что могут быть отличия.

По поводу сюсюкания.
Ваша сила в интернете, как всегда повергают меня в благоговейный страх.
Э… Вы собираетесь 30М запросов отдавать в один поток?

Уже всего на сотне потоков получается 288мс на запрос :)
1. У вас есть сто процессоров?
2. У вас все ресурсы так офигенно масштабируются: hdd, сеть, сторадж?
1. У меня четыре ядра и несколько сот потоков.

2. Именно потому, что ряд ресурсов не масштабируется, у меня несколько сот потоков. И 16Гб оперативки (ибо она «масштабируется» куда лучше, чем HDD).



30, не 30, но несколько миллионов запросов в сутки я отдавал даже на древнем Xeon-1800. И до 80-90 млн. SQL-запросов в сутки.
1. Вы отлично умеете придираться к цифрам, выдирая их из контекста. Я к слову, не указал в статье абсолютных цифр, чтоб таки не провоцировать таких вот споров.

2. Можно заранее знать, например, если это код, который превращает текстовые смайлики в графические.
Правильно, вы указали их в комментарии. И я дал ответ на комментарий в контексте поста. Ваши необдуманно брошенные слова спровоцируют миллионы новичков на новые «подвиги».

2. Можно. Приведите цифры из конкретного проекта, в котором замена str_replace была решающей и в которой был bottle neck.
«Ваши необдуманно брошенные слова спровоцируют миллионы новичков на новые «подвиги»»

Вы меня с Котеровым не путаете? Какие еще миллионы?
Вы сейчас, хотите, чтобы я сверхъественным образом отредактировал свой комментарий?
Или вы хотите, чтоб я раскаялся?

Я уже сказал, что цифра была выбрана абстрактно, моя ошибка, что это было неочевидно.

2. Те же смайлики, а также парсинг коротких тегов, позволяли сократить среднее время обработки на 10-15%, думаю, абсолютные числа с моего ноутбука или VDS вам не нужны?
Опять 10%. Опять необдуманно? Вы какой пример имеете ввиду — который 300rps, или который 2400ms на генерацию?
Если первый — тогда вы опять лжёте.
Если второй — тогда там есть куда более явные проблемы, чем поиск-замена смайликов.
«Опять лжёте.»,
У меня, извините, слов нет, после таких заявлений.

Пример взял из своего конкретного кода, 20 ms -> 18 ms, устраивает? Может сорцами сверкнуть? =)

Просветите насчёт явных проблем, если уж решили идти до конца.
Явные проблемы — это 2400ms на страницу. Если только там нет в том же потоке кодирования видео/картинок/звука или математики — это уже запашок.
Эээ, могу в личку вам скинуть ссылку на популярный движок для городских сайтов, который даёт такие результаты на конфигурации 8 ядер/8 гигов.
Не, меня изкоробочные CMS и прочие блогодвижки не интересуют. Да и никогда в жизни не интересовали :-)
Меня тоже, свой код держу в пределах 25-50 ms, но пришлось поддерживать эту жуть.
ни одной.
покажи такой
да любой
ну какой, например?
смарти
grep -c 'replace' /usr/share/php/smarty/*
/usr/share/php/smarty/Config_File.class.php:2
/usr/share/php/smarty/debug.tpl:0
/usr/share/php/smarty/internals:0
/usr/share/php/smarty/libs:0
/usr/share/php/smarty/plugins:0
/usr/share/php/smarty/Smarty.class.php:3
/usr/share/php/smarty/Smarty_Compiler.class.php:31
$property_name = preg_replace_callback('/([A-Z])/', $camel_func, $property_name);

и чо?
/usr/share/php/smarty/Smarty_Compiler.class.php:
$compiled_content = str_replace($tag_guard, '<?', $compiled_content);

А вот чо.
и сколько раз на странице происходит перекомпиляция шаблонов? х)
Признайте фейл, вот и всё.
сразу вопрос — а тестировалось-то с каким-нибудь компилятором?! тот же APC или еще что. А то вроде как про 30 млн хитов речь, а вот про тесты не понятно.
Цифры для иллюстрации, не с тестов.
Вопрос кстати не сразу понял. Вообще, xCache стоит.
Ну иногда проблемы бывают далеко не в базе, как посмотришь иногда на чужой код, так диву даёшься как это вообще ещё живо.
Я думаю, каждый хоть раз видел код, в стиле:
for ($a = 0; $a < count ($arr); $a++) do();
Я кстати тестировал подобную конструкцию на произваодительность. Как оказалось, главный тормоз здесь — вычисление count ($arr) на каждой итерации цикла. Ну это так, к слову.
Кхм, вообще-то это как раз таки пример хрестоматийно медленного кода, и проблема с count() очевидна =)
Или это была ирония?
Да нет, просто я сам в свое время понял, что главный тормоз здесь это count() только после того как сравнил результат с кодом, где count() вычислялся один раз. Не сказал бы что это настолько очевидно.
Если что, я не минусую оппонентов.
Я бы тут предъявы кидал к интерпретатору, а не к разработчику.
Тут всё однозначно, причём тут интерпретатор?
Даже если он внутри кеширует результат каунта, то не стоит списывать со счётов расходы на вызов функции.
А Common subexpression elimination происходить не должен?
Насколько я помню, это из теории компиляторов.
В PHP видимо посчитали, что для интерпретатора такая замена не нужна.
Я к тому, что если $arr внутри вызова $do не модифицируется, я ожидаю, что нормальный компилятор сделает так:
$tmp_arr_count = count ($arr)
for ($a = 0; $a < $tmp_arr_count; $a++) do();


Если вдруг выяснилось, что он этого не делает, и у меня вдруг это вылезет как узкое место, я скажу «гм» и сделаю это сам. Но только если вылезет на профайлере. Вообще странно ожидать такого от программиста.

Это какой-то каменный век. Типа древного
Inc
в Borland Pascal. Компилятор разворачивал оператор:
i:=i+1;

в машинный код
 mov ax, [i]
 inc ax
 mov [i], ax

вместо того, чтобы делать:
inc [i]

Чтобы получить нормальный код, была специальная функция-макрос:
Inc(i);
Компилятор — это компилятор, у него во-первых есть время делать такие оптимизации, во-вторых есть возможность, так как чаще всего компилируемые языки — со статической типизацией, массивами, а не хешами, с ограниченной размерностью этих самых массивов и т.д.
for($a = 0; $a < count($arr); $a++) {
  array_push($arr, 'newvalue');
}

И оптимизация ломает логику, а в php это вполне себе работающая конструкция.
Я же написал, если do() не модифицирует $arr. Определить это в большинстве случаев можно.
В том числе и в языках с динамической типизацией и хитрыми массивами (javascript)
Это не всегда возможно, и не всегда доступно малой кровью, нежели гадать настолько-ли умен компилятор чтобы додумать программу за меня — мне проще написать самому for($i = 0, $j = count($array); $i < $j; $i++);, так как я-то точно знаю изменяется-ли размерность массива внутри цикла или нет.
Не надо ничего гадать, надо писать самым прямым способом. Если это было узкое место — оно на профайлере вылезет.
Если язык поощряет писать «непрямым» способом, значит что-то не так.

В данном случае не с языком, а с интепретатором.
Так предложенный мной способ — он и есть прямой, даже на компилируемых языках писать так — правильно, несмотря на то что на них отследить подсчет цикла более реально. Си-подобный цикл for выглядит так:
for(инициализация; условие; инкремент); — первое выражение выполняется единожды, последующие два с каждой итерацией, вынесение count() во второе выражение указывает что он и будет выполнятся каждую итерацию, то что какие-то компиляторы могут на достаточном уровне проанализировать код чтобы понять будет-ли изменяться размерность массива — еще не значит что так и надо писать.
Писать надо так, как оно в итоге должно выполнится, а не гонять потом программу в профайлере туда-обратно «угадал — не угадал?».
Писать так, как оно «в итоге должно выполнятся», не надо.

Компилятор — программа, созданная, чтобы упрощать мою работу. Программист должен писать «что нужно сделать», а не «как это нужно сделать». Чем более высокий уровень — тем больше простора мы даем нижним уровням для оптимизации.

В этом плане лучше всего написать foreach, на самом деле.
Интерпретатор — не компилятор, как я уже выше написал, у компилятора гораздо больше времени проводить оптимизации, от него никто не ждет результата здесь и сейчас, он может анализировать код часами, насчет «что нужно сделать» и «как нужно сделать» — это споры насчет империтивного и функционального программирования, обе методологии имеют право на жизнь, но «что нужно сделать» относится ко второй, а php — к первой.
Ну и мои хвалебные оды foreach в конце топика :P foreach — это правильный пример оптимизации и облегчения жизни программиста, это отдельная языковая конструкция у которой заведомо известно что и как она исполнит.
У других интепретируемых языков CSE есть. Не везде, но в hotspot — есть.

Да, я тоже в общем случае за foreach, именно потому что, она более высокоуровневая.
Кстати, простите тупого, а этот цикл закончится? Мы на каждом шагу добавляем новое значение и никогда не догоним count($arr). Или я чего-то не понимаю?
Закончится по истечению 30 секундного интервала, если через set_time_limit() не задан другой интервал, это в данном случае актуально?
Это я на всякий случай. :)
Компилятор может вынести результат count() за пределы цикла только если будет знать что выращение внутри count() не меняется во время выполнения цикла. Если для простого скрипта вывода это проверить можно, то для многопоточных выражений — нет. Поэтому в данном случае «оптимизация» — за программистом.
Для к-каких извините, многопоточных выражений? Если $arr не глобальная переменная, то как она может существовать в другом потоке?
Ну и что значит «не нужна». CSE даже javascript интерпретаторы делают, а им вдруг не нужна.
имхо оставлять без особой необходимости в цикле вычисления которые из цикла можно вынести это писать плохой код.
компиляторы/интерпретаторы тут не виноваты.
Ага, давайте так:
foreach ($arr as $el)
{
   echo $el + 1/3;
}

Я правильно понял, что в этом цикле каждый раз будет выполнятся деление с плавающей точкой? И нужно писать на самом деле вот так:

$one_third = 1/3;
foreach ($arr as $el)
{
   echo $el + $one_third;
}
Мне вот тоже казались, что рассуждения какие кавычки быстрее в приличном обществе давно запрещены.
Если я правильно понимаю, то в этом посте не содержится советов по той самой «преждевременной оптимизации, что является корнем всех зол». Здесь рассмотрено несколько правил, улучшающих производительность не в ущерб разработке — т.е. использование более быстрых синонимов/аналогов, не ухудшающих читабельность кода.
Да, преждевременная оптимизация, обычно связана с неуместным усложнением архитектуры кешированием, предвыборками и т.п.
Это тоже верно — если конструкции выглядят одинаково адекватно — почему бы и не применить наиболее быструю. Но вот о чем подумает новичок, прочитав такую статью? Он конечно же воспримет её как руководство к преждевременной оптимизации.

Например, нотисы. Почему их нужно избегать? В первую очередь — не из-за оптимизации! Допустим, некий прогер разработал проект в котором решил забить на нотисы. Т. е. начал написал код так, что нотисы возникают и это считается для него нормальным тоном. Все равно на продакшне display_errors = off. И тут оказывается что логи сервера разбухают непомерянно — на каждый хит нотисов вылезает десяток штук. Устанавливаем error_reporting пониже — получаем проблему с дебагом кода.
Я указал, что если аргумент с хорошим тоном не прокатывает, но программист беспокоится о скорости, это еще один рычаг воздействия, ни в коем случае, не первостепенный.

«Он конечно же воспримет её как руководство к преждевременной оптимизации.»
Мне кажется, это слишком однозначный вывод.
На самом деле, конечно же, тоже неверно.
Большая часть всех этих «оптимизаций» не приведет к измеримому приросту скорости работы приложения.
И не выглядят они одинаково. С какой стати include_once стал выглядеть, как include? Оператор выбирается по требуемому функционалу, а не потому что какой-то дядя сказал, что один быстрее другого.
Нет, содержится.
Преждевременная оптимизация — это именно стремление оптимизировать там, где не надо.
Причем, что забавно — реально производительность как раз не увеличивается.
Вбор между count и sizeof может быть обусловлен чем угодно, но только не разницей в производительности.
Сам подход в принципе неверен. Вместо профайлинга, который и является единственным основанием к оптимизации, тут просто набор рецептов.
Оговорка «на вашей системе результаты могут быть другими» выдает автора с головой. Это именно попытка преждевременной оптимизации и ничто другое.
Слушай, срыв покровов прямо какой-то.
Я всегда думал, что преждевременная оптимизация, это стремление оптимизировать не тогда когда надо, как бы преждевременно. А ты мне глаза открыл =)

Даже на Debian и Ubuntu, PHP иногда ведёт себя по разному, чего говорить о мире RPM-based дистрибутивов.
Опять же, у меня нет под рукой FreeBSD, а на ней есть свои особенности.
Поэтому там и есть эта оговорка.

Набора рецептов, или практик, тут не было, вам показалось. Тут просто список особенностей поведения.
Каждый сам определит для себя их полезность.
Мы тут вчера решили профайлером пройтись по одному проекту, доставшемуся нам от фирмы «X».
400+ запросов к мускулу на 1 страницу. а вы тут на count() и sizeof() экономите…
Ну, подобные проблемы, слава богу, давно в прошлом.
Я помню, в 2004 году, начинал писать свою систему на Athlon XP2400 / 256 RAM под windows, и у меня каждый лишний запрос, «кожей ощущался», можно было на вид определить сколько запросов было =)

В следующих топиках, затрону тему правильной предвыборки и поствыборки из хранилищ данных.
Проект новый. компания довольно известна в городе екатеринбурге, но проблема есть
клиент лучше будет платить за вдс с 1500мб памяти и кучей проца, чем один раз переделает сайт у фирмы с нормальными программистами. чтобы не быть голословным
Да, это странно, платить каждый месяц, вместо единовременных оптимизаций.
Между прочим, от фразы «Преждевременная оптимизация — корень всех зол» недалеко ушла фраза «Как-нибудь сделаем, а потом исправим», и не надо путать одну с другой.
Да, вы очень правильно всё поняли.
Одно дело, прикрутить memcached к начавшему тормозить mysql, другое, grep-ать и search&replace'ить весь код, заменяя куски кода.
Это просто набор полезных ненапряжных привычек.
Пусть simplexml_load_file работает хоть в 2 раза медленнее, но он при чтении файла выглядит логичнее. Стало быть если в какой-то из следующих версий РНР может его и сделают быстрее, то ваш некогда быстрый код, как читался неудобно так и будет читаться дальше, а это сильно скажется на дальнейшей поддержке кода. Особенно это будет заметно с file()
Приведу вам контр-пример.

У меня получение данных, абстрагировано классом, который скрывает реальный источник данных: БД, файлы, мемкешед, веб страница, и предоставляет единый интерфейс.

Я склоняюсь к соблюдению «unix way» и концепции «pipes» не только в целых скриптах, но и в функциях.
Мне нужна логика, которая разбирает xml. И только.

Как раз таки, когда мы берём под контроль процесс получения данных, мы повышаем гибкость и обслуживаемость кода, а не оставляем его на милость «может его и сделают быстрее».
Вот вы и сами в попытке опровергнуть моё мнение, только подтвердили его.

В вашем случае у вас совершенно другая ситуация, вам будет нужен file_get_contents, НО, не потому что он работает быстрее чем «simplexml_load_file», а потому что У ВАС в приложении просто архитектурно не предусмотрен таковой, и вы передаёте данные именно в «simplexml_load_string»!!!

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

file_get_contents — он, образно выражаясь, специалист по получению файлов.
simplexml_load_file — дилетант, который хватается за два дела.
Часто еще забывают, что множественная конкатанация строк — очень медленная операция.
вместо
$result='';
for($i=0;$i<=100500;$i++){
$result.='<option>'.$result.'</option>';
}

лучше сделать
ob_start();
for($i=0;$i<=100500;$i++){
echo '<option>', $result, '</option>';//при echo используем запятую между фрагментами, а не точку
}
$result=ob_get_clean();

Об этом хорошо очень на phpbench.com написано, советую.
В своей статье, я решил не повторяться, об этом часто пишут, и часто забывают.
На phpbench не увидел варианта, когда нужно в результате получить строку, а не вывести её. Как показывает опыт общения с программистами, ob_ функции очевидны далеко не для всех.
Мне кажется, в проекте echo должен быть только один, не смотря на преимущества ob_.
Тот, который выводит отрендеренную переменную.

Это повышает удобство отладки и ясность кода, имхо.
На сайтах портального типа я сторонник блочного построения страницы, когда у каждого блока свои настройки кэширования. При отсутствии нужного блока в кэше — он рендерится в строку и ложится в кэш в соответствии со своими настройками. Как такого достичь без буферизации вывода — я не знаю.
Я к примеру, использую класс, который вызываю вместо echo, а он сам раскидывает это по своим внутренним массивам и внешним кешам.
Можете описать чуть поподробней?
Например, есть страничка, на которой выводится телепрограмма (инвалидация в полночь), популярное видео (обновляется раз в час), последние новости (обновляется раз в 15 минут).
Как этого можно добиться классом, заменяющим echo?
Логичнее, наверное, в личку.
Сложно описать, не зная, какая у вас архитектура.
Легко — вместо echo использовать return!!! )))
А разве если я делаю echo сразу заголовки страницы не отсылаются пользователю?
Просто могут возникнуть проблемы, если их менять будут.
Если ob_start() включён, то echo можно делать спокойно.
Если нет, заголовки после echo вы не измените.
for($i=0;$i
Если output_buffering=off, то можно

$_temp = array();
for($i=0;$i<=100500;$i++){
$_temp[] = "<option>{$result}</option>";
}
$_temp = join('', $_temp);
Сравнивал в свое время скорость работы с public полем и вызова геттера/сеттера этого поля с работой магических методов __get, __set и __call.
Для 1000 итераций получились следующие значения (в секундах):

getFieldValue():0.0013
_field(получение):0.0003
__get():0.0010

setFieldValue():0.0014
_field(установка):0.0003
__set():0.0012

__call():0.0024


P.S. __get / __set / __call были реализованы следубщим способом:
  public function __get($name)
    {return $this->_field;}
  public function __set($name, $val)
    {$this->_field=$val;}
  public function __call($name, $arg)
    {return $this->_field;}
Магические методы очень медленные, это да.
Они бывают медленнее даже такой конструкции как

function get($Key)
{
return $this->$Key;
}
В __get и getFieldValue() был одинаковый код. __get() оказался быстрее почти на четверть.

А медленней они простого getFieldValue за счет того, что в них помимо «return $this->Value;» надо какую-либо логику реализовывать.
Но это все равно не объясняет, почему Ваш get($Key) быстрее аналогичного __get.
Думаю, перед тем как вызвать магическую функцию, интерпретатору нужно пробежать по всей таблице методов и полей.
Согласен, что по идее так и происходит.
Но почему тест показал что __get быстрее?
getFieldValue():0.0013
__get():0.0010

Внутри один код в обоих случаях:
{return $this->_field;}

Возможно, при вызове __get сигнатуру метода мы уже знаем и нам не надо ее сопоставлять. А при обычном вызове функции надо сопоставить параметры.
Но все это догадки. Магические методы имеют особый статус и по особому обрабатываются. Простое получение поля все равно быстрее в 3 раза, а __call медленнее обычных методов в 2 раза.
Но тут надо помнить, что в свою очередь геттер медленнее получения public-поля в 4 раза.
Возможно, потому что получить неустановленное поле мы не можем, а установить — можем.
Потому и логика, и результаты отличаются.

Спасибо за статистику по геттерам, сам не использовал, подсознательно =)
Не нужно. Операция поиска метода — O(1)
Есть альтернативные предположения?
Зачем? Это не так?
Я имею ввиду, есть предположения, почему интерпретатор так себя ведёт =)
А, хехе :-) Нет. Я над такими вещами не заморачиваюсь. Я пишу так, как мне удобно писать и как по моему разумению писать правильно.

Оптимизация — дело далёкого будущего.

А подобные микро-оптимизации — скорее всего вообще, несбыточного.
Если в __get обратиться к полю в $this, то сработает еще один __get. Но дальше PHP как-то распознает, что это будет продолжаться вечно и просто выдает значение поля. Магические методы реализованы крайне странно в PHP)
На то они и магические =)
Спасибо за пост. Мне, как и многим другим, кто стремится сделать свой код лучше и быстрее — такое полезно.

Было бы здорово увидеть обзор многих других функций и блоков php в их сравнительной скорости выполнения.
Очень рад, что первый топик кому-то понравился.
Я разрабатываю свой фреймворк (как бы это банально не было), и набралось достаточно разных опытов, не только с простым php, но и с более сложными конструкциями.
Постараюсь писать топики почаще, спасибо =)
А на самом деле надо стремиться сделать быстрее работу приложения.
>>Скажу лишь, что перейдя на json-файлы для конфигурации…
А почему бы не хранить конфиги в нативных массивах php? Будет еще быстрее.
Прелесть конфигов в читаемых форматах, что их может редактировать человек, не знающий php.
Я бы не пустил незнающего человека редактировать JSON-конфиг тоже, но на вкус и цвет…
Не совсем незнающего, например системного администратора.
Спасибо за линк, некоторые вещи устарели, но в целом, всё очень правильно.
Там автор очень суровый человек.
У него $i++ и ++$i в реальном проекте были узким местом.
Насчет производительности множественной конкатенации строк осмелюсь оспорить. Если вы склеиваете много маленьких строк через массив — расходуется впустую память и процессорное время на операции с нею.

pastebin.com/Wz1QvZ74 — скрипт для тестирования предложеного мною случая и его вывод на моем сервере с php 5.3

warmup job: time: 0.003025 | memory: 606092
warmup flush: time: 0.003353 | memory: 532

array job: time: 0.002856 | memory: 605688
flush: time: 0.003168 | memory: 108

concat job: time: 0.001687 | memory: 100096
flush: time: 0.001697 | memory: 104

10к элементов по 10байт — в случае с массивами расход памяти в 6 раз больше, расход процессорного времени — 2 раза. Также заметно, что PHP требуется больше времени, чтобы освободить память после работы с массивом. Это тоже надо учитывать.

Склейку через массивы можно производить с большими строками (в webdev такое редко), а не преподносить как общую панацею от тормозов.

В моем случае я тоже склеивал раньше все через массивы, пока не перешел к более-менее серьёзным объемам, от которых пхп начал вываливаться за memory limit 256Мб, при объеме данных на 2-5Мб, кусочки были разные, 100-10Байт, просто их было много. Переход к тупой последовательной склейке строк дал мне расход памяти на эту операцию всего в районе 16Мб и немного увеличившееся время генерации содержимого.
Баланс между памятью и скоростью, это, к сожалению, вечный компромисс.
Погонял тестовый скрипт немного, на моей конфигурации паритет между методами (и память, и время) достигается при размере элемента склейки 1400 байт. Накладные расходы на выделение 10к элементов массива постоянны и равны 505Кбайт:

warmup job: time: 0.195462 | memory: 14506056
warmup flush: time: 0.197994 | memory: 520

array job: time: 0.201980 | memory: 14505740
flush: time: 0.204485 | memory: 96

concat job: time: 0.196722 | memory: 14000096
flush: time: 0.198964 | memory: 104
warmup job: time: 0.008601 | memory: 1432624
warmup flush: time: 0.009776 | memory: 1376
array job: time: 0.005844 | memory: 1431352
flush: time: 0.006614 | memory: 240
concat job: time: 0.003305 | memory: 100248
flush: time: 0.003358 | memory: 240

64 битная система, видимо из-за этого расход.
ты память некорректно сравниваешь.
в версии с массивом ты измеряешь пиковое потребление
в версии со склейкой ты фактически измеряешь объём результата. без учёта используемого при склейке буфера.
Я совсем не против увидать более корректный скрипт сравнения методов.
$start_mem = memory_get_usage();
$start_time = microtime(true);

$ret = '';
$arr = array();
for ($i=0; $i
$start_mem = memory_get_usage();
$start_time = microtime(true);

$ret = '';
$arr = array();
for ($i=0; $i$lt;$num; $i++) {
$arr[] = $chunk;
}

$ret = join ('', $arr);
$arr = array();

printf("\narray job: time: %f | memory: %d", microtime(true)-$start_time, memory_get_usage() — $start_mem);

$ret = '';

printf("\nflush: time: %f | memory: %d", microtime(true)-$start_time, memory_get_usage() — $start_mem);
Ну вы же не глупый человек, я измеряю память которая требуется для проведения операции склейки, а не итоговую (а вот пиковая память, memory_get_peak_usage может дать еще больше).

Какой мне профит от того, что результат склейки займет пять мегабайт в памяти, но при этом сама склейка вывалится из-за memory_limit на строке $ret = join ('', $arr), а может и того раньше?
ага, и у тебя получается, что потребляемая инкрементальной склейкой память вообще равно 0, потому как то, что ты вычисляешь — это объём результата. а все промежуточные буферы уже автоматически очищены.
в случае с массивом ты сам создаёшь буфер, но не очищаешь его перед измерениями

правильно, ведь измерения как и проводились для того, чтобы измерить объем памяти, используемый массивом. Простите, мне уже невыносима роль Капитана Очевидность, позвольте сложить полномочия )8. Можете считать этот моим сливом в споре с Вами.
но память используемую конкатенацией ты _не измеряешь_
предположу (2xFINAL_STRING_SIZE — last_chunk_size), как освобожусь — постараюсь измерить, думаю в этом деле поможет memory_get_peak_usage

Мое предположение исходит из наивного алгоритма, которым пугают маленьких детей: выделить новый блок памяти размером (старый + строчечка), скопировать туда данные, грохнуть старый блок. Т.е. наибольшее использование памяти, когда выделены оба блока.
при таком алгоритме странно, что оно работает в 2 раза быстрее.
на самом деле по ощущениям кажется, что он не выполняет реальную склейку, а лишь создаёт связный список.
Скорее всего вы правы, погонял сейчас тесты на склейку строк — вне зависимости от размера элемента и их количества оверхед памяти ~1100байт на все данные.

Такое ощущение, что memory_get_usage говорит не всё. Имеет смысл погонять склейку при низких значениях memory_limit, чтобы из сообщений об ошибке узнать сколько памяти php хотел выделить на очередной этап.
не, лучше вообще на виртуалке с критически низким количеством памяти гонять. а то когда я тестировал xslt эти функции показывали, что он ничего не кушает, а жрал он у меня огого по диспетчеру задач х)
Более корректный — это ab на реально делающий что-то код.
Желательно — под нагрузкой.
У меня реально работающий код под нагрузкой 1-10RPS (зависит от времени суток), немного, но хватает для получения опыта.
Советую попробовать siege вместо ab.
Ну вот в этом реально работающем проекте поменять один сравниваемый метод на другой, померять, поменять обратно и снова померять.
Увидим разницу — начнем думать, как оптимизировать (hint: — совем не обязательно на тему смены одной функции на другуюю К примеру, в первом классе детей учат, что если возникают проблемы с чтением большого файла, надо не file() на file_get_contents() менять, а подход в целом, не запихивая весь файл в память целиком)
Не увидим — просто пожалеем о потраченном времени и пойдем займемся чем-нибудь полезным. Профайлингом, например. Который нам заранее скажет — стоит ли возиться с данной конкретной разницей между конкатенациями, или нет.
В этом интересно покопаться с теоретической точки зрения. Но для практической оптимизации — только профайлинг. Качественный, а не искусственный. профайлинг приложения, а не кода, который ничего не делает
Да, подходы меняю потихоньку… поменял strtok на ExplodeIterator от WikiMedia, это из серии «читать, не запихивая всё сразу в память»
Странно что foreach упомянают в суе, по сравнению с конструкцией
while (list($key, $value) = each($item))
он всегда будет быстрее, each это наследие старых версий php.
Да, но 9 из 10 статей о производительности, отрицают этот факт, почему то.
Ну наверное потому что это не круто :) не видно факта оптимизации :) можно еще по массиву так:
for(reset($array); $key = key($array), $value = current($array); next($array));
пройтись, так совсем оптимально :)
Вы сняли штаны с foreach() :-)
Недавно ради интереса тестировал пару подобных мелочей.
Выяснилось, что двойные кавычки в последних версиях php таки быстрее одинарных, как бы странно это не звучало. Разумеется, если не использовать упоминание переменных прямо внутри строки, для этого используется конкатенация.

А foreach оказался быстрее, чем for(;;) на массиве с числовыми индексами, расположенными по порядку. Это еще более странно, но факт.

Можете проверить)
foreach всегда был быстрее! foreach — лучший! foreach — наш чемпион! foreach! foreach! :P
А быстрее он потому что оптимизирован под то чтобы бегать по массивам, в случае for идут отдельные накладные расходы на инкрементацию счетчика на уровне php, и поиск нужного индекса каждую итерацию при обращении $array[$index], foreach-же делает это все сразу скопом на уровне си, вот если-бы php был языком компилируемым, и массивы-бы у него были массивами а не хешами, и типизация статичной — то конечно for-бы выиграл.
Рискну предположить, что массивы в пхп интерналс таки реализованы в виде хэшей.
Ну я как-бы про это и пишу :)
А, пардон :-)
Пожалуй вы правы, не задумывался об этом. Это конечно делает все намного понятнее)
На самом деле foreach удобнее. Универсальнее.
А если на критическом к времени выполнения участке обрабатываемый массив имеет такой размер, что заходит речь о сравнении различных методов его перебора, то надо, префразируя известный анекдот, программистов менять, а не функции местами переставлять.
Копаться в потрохах всегда интересно. Но делать это в таких топиках — это играть с горе-оптимизаторами на их поле, в игру быстрее-медленнее.
надеюсь, for был не в такой форме
for($i=0;$i<count($array);$i++)

во всяком случае, $array[$i] заставляет каждый раз искать позицию в массиве пробегая его от первого элемента к последнему, когда как в foreach сдвигается лишь внутренний указатель на следующий элемент. На больших массивах это заметно
Вы меня наверное за человека, первый раз пишущего программы принимаете :D
$cnt=sizeof($array);
for ($i=0;$i<$cnt;$i++)

$array[$i] уж точно не пробегает от первого к последнему, все массивы в php это же хэши по сути. Я думаю, поиск там побыстрее, чем полный перебор)
мало ли, лучше уточнить :)
массивы в пхп это связные списки или деревья (хотя в этом сомневаюсь), в любом случае for(;;) делает больше одного просмотра элемента
Плохо знаю С++. залез в исходники. zend_hash.c:60
это структура похожа на двусвязный список с избыточными данными: с указателями на начало и конец, указателем на текущий элемент. Каждый элемент имеет указатель на следующий, предыдущий, свой номер ну и данные.
Название файла ни о чем не говорит?
Хэш-таблицы там.
Говорит-говорит. Я просто не реализовывал хештаблицу и не очень знаю её внутреннюю структуру. Читаю педивикию.
интересная у них функция вычисления хеша (hash.h:261) и магическое число 5381.
Используется хеш с открытой адресацией. Массив представлен в виде связного списка, каждый элемент которого получается, тоже связный список но уже конкретно значений.

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

только что за 5381 и почему сдвиги на 5 позиций бит влево?
Статей много, я решил не повторять все-все-все известные хинты.
А мне вот не верится! Нужны детальные тесты под разные платформы, в условиях близких к идеальным и с соблюдением тех.процесса :)
«Свой профайлер, я настроил (на testing-машине) на выброс исключений, при аномальном замедлении каких-либо участков кода (пример: «Achtung! 30% времени на подключение к MySQL»).»

А можно по подробнее, чем меряете?
XHProf и XDebug + KCachegrind, стараюсь перепроверять всё.
Но еще использую свой код, который в рантайме генерирует эти самые исключения.
Ради всего святого в программировании, не пишите таких постов для новичков. Хотя бы припишите, что в подавляющем большинстве случаев так нельзя подходить к оптимизации кода. Вам тут правильно народ грамотный пишет, это не ботелнек и прикидки все ооочень натянуты. Определено инфа была бы полезной, если были бы видные нормальные тесты. А так это из серии MySql круто, Oracle гавно. Хотя все примерно так и есть, я сейчас не про базы)
Учту.
видимо не учли. Удачного общения с такими новичками)
Автору спасибо! simplexml_load_string( file_get_contents ('file.xml') ) — понравилось… Не понимаю ниразу возмущающихся, человек показал на своем опыте как можно простыми вещами облегчить жизнь серверу, никто не заставляет кодить именно по показанным примерам, наоборот автор призывает самим анализировать работу тех или иных структур кода для определения оптимальной работы для той или иной архитектуры сервера, а если у вас стоят другие задачи то просто взять на заметку всегда полезно. Вообще обмен опытом это всегда хорошо…
автор пишет для новичков, которые это рьяно берут на вооружение. Я сам работаю почти 10 лет, таких горе оптимизаторов навидался, которые с пеной у рта доказывали, что они знают в чем проблема «вот тут регулярка юзается, ща перепишу все за час и будет всем хорошо». Естесно все было не за час, а за 2-3 дня и результат ноль. Надо просто написать жирным шрифтом в начале топика, что в 98% случаев вы не сможете так оптимизировать приложение целиком.
В топике нет слова «панацея» =)
На самом деле, чтобы облегчить жизнь серверу, надо переписать приложение так, чтобы ему не требовалось часто открывать большой файл.
Вот это действительно будет «облегчение».
А поиск функции, которая выполнит эту тяжелую операцию на 2% быстрее — это игра в куличики, а не оптимизация.
Ссылка на mmap присутствует. Этот алгоритм, даёт больше 2%.
Только хватаясь за JSON, важно не переборщить, ибо нет (я лично не видел) библиотеки, которая читала бы JSON последовательно. Так что для передачи больших объемов данных по-прежнему лучше XML: на передающем конце банально выводим его print'ами (если он простой, ну а если сложный, то придется, наверное, пользовать XmlWriter), на принимающем юзаем последовательный XmlReader.
Да, я в курсе про поточную генерацию, речь шла о небольших конфигах.
Кстати, про последовательный разбор JSON, отличная идея, попробую написать.
Вы видимо имеете ввиду SAX и DOM
Ну XmlReader вроде как и есть SAX-читалка. А в DOM я в данном случае смысла не вижу, ибо после парсинга XML предпочитаю иметь массивы, которые можно передать дальше в функции.
Deprecated: Function ereg() is deprecated…


Не стоит забывать.
Читайте топики иначе, чем по диагонали.
mb_ereg никто не отменял.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Потому что разговор о серверной оптимизации.

GZip — это клиентская, и она лишь увеличивает нагрузку на сервер, хотя и очень полезна.

Убирать кавычки, можно только если в аттрибутах ASCII без спецсимволов, да и валидатору это может не понравиться.

Не использовать ООП — это луддитский совет, но я согласен с ним наполовину, не стоит плодить классы ради классов (дедушка Оккам мне роднее настоящего =)).

А функции, они в любых языках с оптимизаторами, прекрасно жмутся, и, вообщем-то, ЕМНИП, код, целиком распиханный по функциям, будет работать лучше.
НЛО прилетело и опубликовало эту надпись здесь
Соединения с базой должны обрываться раньше рендеринга и вывода, я считаю.
Дык, сжатие тоже не дешёво даётся, и тоже висит скрипт.

Так что, гзип, палка о двух концах. Но повторю — необходимая.
(режим К.О.)
Зависит от ситуации и от целей, иногда GZip может выиграть гигабайты трафика иногда мегагерцы процессора, иногда просто «просрать» мегабайты оперативки… Каждая ситуация уникальна, нужно только искать баланс (и он разный в разных случаях)
Абсолютно верно, не понимаю, почему многие так резко реагируют, как будто я на мраморе что-то выбил, и вожу джуниоров по пустыне.
Любой highload, это штучная вещь. И всё надо испытывать на своём коде, любое замечание.

Очень многие советы, у меня не срабатывали, просто из-за небольшой экзотичности системы, хотя в простых тестах, результаты совпадали.
Весь прирост может растеряться по дороге к выводу.
Не панацея, но тоже вариант — поставить прокси (nginx например) перед веб-сервером
Реверсные прокси, уже вошли в джентльменский набор, хоть и не относятся напрямую к теме топика.
И кстати, на них можно и gzip сжатие вешать, надо бы провести тесты, что быстрее сжимает, php или nginx etc.
Перед апачем стоит ставить фронтэнд, тогда время загрузки страницы клиентом абсолютно никак не скажется на времени висения апача и пхп в памяти для обработки запроса.
Вынос CSS и JS в отдельные файлы и использование output buffer – это само собой в любом проекте, даже небольшом. Но вот за вёрстку без кавычек, отсутствие табуляции/форматирования кода и неинформативные названия переменных нужно, простите, бить лопатой. Для продакшна в высоконагруженных проектах можно использовать обфускацию, это действительно даст большой прирост производительности, но исходный код в таком виде – натуральная диверсия.
explode("\n", file_get_contents('file.xml'));

не может заменить file(), так как нет в этом варианте учета разных окончаний строк. Это можно решить, но уверен что решение будет дороже чем использование file().
Я уже отвык, что существуют иные ОС, кроме nix-like, mea culpa.

В данном случае, мы можем \n заменить на константу, которую будем определять один раз, на базе PHP_OS.
Кстати, не удивлюсь, если есть уже такая в SPL.
Есть, PHP_EOL
О, спасибо, обновлю топик.
поспешили (или я опоздал?)

PHP_EOL выдает окончание строки в зависимости от системы на которой бежит, что крайне удобно для вывода. Но, если попробуете использовать как написали, то файл с линуксовыми окончаниями на винде или маке прочитается как одна строка.

так что не вариант.
Ну в гомогенных условиях, прокатит =)

А вообще, я винду всерьёз не воспринимаю.
здесь речь не о любви у винде или маку, а о работоспособности кода. Указанный пример не заменяет функционал file() и наверное стоит вынести это из статьи, дабы не вводить кого-либо в заблуждение. Скорей всего такой файл придет как user input на обработку и если не учитывать такой простой момент, то все кончится крайне плохо.
Можно либо зафиксировать это дело, либо определять на лету.
проблему решить можно, но решение будет медленней чем file() и соответственно заменить эту функцию не может в пользу оптимизации. Как раз то что и написали про использование встроенных функций вместо своих велосипедов.
Маки тоже nix-like, а окончания строк как раз другие.
почему не пишите, что дорогим может быть обращение к файловой системе? я бы рекомендовал держать конфиги в кеше, а не брать их из файловой системы
Кэширование, это не панацея, как раз таки.
Разумеется, можно держать без проблем весь проект в памяти.
Но это, не решение проблемы, а прокрастинация.
Я разве сказал, что нужно держать в памяти весь проект? Я говорю, что операции с файловой системой достаточно дорогие на высоких нагрузках.
Я разве спорил, или приписывал вам свои слова? =)
советую заменить file() на
explode("\n", file_get_contents('file.xml'));
Прирост будет еще больше, чем в случае с xml.


Бред. Если бы вместо гадания на кофейной гуще о том, как устроена функция file(), автор посмотрел в исходники, то увидел бы, что собственно чтение файла реализовано абсолютно одинаково у обеих функций, и вообще чуть ли не все файловые функции используют один и тот же php_stream_xxx интерфейс.
Я даже протестировать не поленился — в пределах погрешности один в один.
Если поделитесь кодом, которым тестировали и описанием окружения, будем признательны.
Извольте:
<?php

if (!file_exists('test.file')) {
  $f = fopen('test.file', 'w');
  for($i=0; $i<500000; $i++) fwrite($f, "String #$i -- some padding -- $i$i$i$i$i --\n");
  fclose($f);
}

$ts = microtime(1);

for($i=0; $i<100; $i++) {
  $x = file('test.file');
  unset($x);
}

print "time: " . ((microtime(1) - $ts)*1000) . " ms\n";
$ts = microtime(1);

for($i=0; $i<100; $i++) {
  $x = explode("\n", file_get_contents('test.file'));
  unset($x);
}

print "time: " . ((microtime(1) - $ts)*1000) . " ms\n";
?>


time: 24141.930818558 ms
time: 25979.696035385 ms

----------------------------------

time: 23707.021951675 ms
time: 24928.278923035 ms

----------------------------------

time: 24311.058998108 ms
time: 24633.358001709 ms

----------------------------------

time: 24932.843923569 ms
time: 25643.95904541 ms

----------------------------------

time: 23347.62096405 ms
time: 24808.028936386 ms

----------------------------------

time: 23740.713119507 ms
time: 25628.977060318 ms


Linux 2.6.18 (CentOS 5) i686, контейнер OpenVZ
PHP 5.2.13

file() даже чуть быстрее, по понятным, впрочем, причинам.
Моя радость будет неполной без test.file, который вы можете положить например на pastebin
Ай, сорри, не заметил, что вы прям там его делаете.
У меня 3 из 4 запусков, file_get_contents сработал незначительно, но быстрее, 1 запуск практически совпал.
2.6.35 Kubuntu x64, desktop, php 5.3.2

Не зря я сделал оговорку в начале топика.
Вот мне кажется, что для таких микрооптимизаций лучше подойдет не замена одних функций другими, а HipHop PHP developers.facebook.com/blog/post/358 Пусть всю грязную работу делает компилятор.
Одно другому не мешает, HipHop шикарная штука, в паре с gcc =)
Конечно, не мешает. Я вот думаю, что люди пост почитают и будут соетами пользоваться — это очень хорошо. А вот старый код вручную лопатить, выискивая все вызовы одних функций и заменяя их на другие, наверное, не стоит. Лучше дать на съедение ХипХопу.
Я выше уже писал об этом, что есть смысл использовать, только если на интуитивном уровне, а не перелопачивать под каждый набор фактов =)
Да вашу мать. Вот прямо вижу как хабрашколота побежала в своих гениальных самописных cms менять file() на explode(file_get_contents()).

За указания «это быстрее чем то» без приведения кода бенчмарков, условий, в которых они проведены, и результатов оных, в приличном обществе записывают в, ммм, гуманитариев.

Более. За одну трату рабочего времени на такие «оптимизации» надо увольнять нахер.

Если ничего не тормозит — работает не трогай. Если есть тормоза — профайлинг, поиск боттлнеков, устранение.

>>Следствие этого:
>>simplexml_load_string( file_get_contents ('file.xml') )
>>работает быстрее, чем:
>>simplexml_load_file('file.xml')

На маленьких файлах пофигу. Большие вообще нефиг simplexml-ем трогать.

>> count() и sizeof()
>> UPD: sizeof() это синоним count(), работает быстрее, спасибо merkushin за поправку.

Вот даже сами запутались. Гы. На миллионе итераций разница в пределах погрешности измерения.

>> Допускать нотисы, это ужасно, да.
>> Но если ваш junior developer, не хочет признавать их важность, расскажите ему, что на
>> генерацию одного notice у PHP уходит время, за которое можно обойти и инкрементировать
>> массив из примерно 30-ти элементов.

Ага, в рамках государственной инновационной программы воспитываем нанооптимизаторов.

Джуниору надо втихаря подправить в незаметном месте его кода имя ключа в «засобаченном» массиве, например, l заменить на I. Пускай потрахается пару часов, и признает правоту наставника.

>> Цикл foreach, практически в каждой статье, посвящённой производительности PHP, предают анафеме

А зачем такие, прошу прощения, статьи, читать?

>> Проверять file_exists() затем делать include, дешевле

Здравствуй, друг из прошлого! Как там живется в MS-DOS? У нас тут, представляешь, многозадачные системы щас, и между file_exists и include может произойти что угодно. Ваще ужас, да.

>> Не знаю почему, но include_once, часто проигрывает по скорости конструкции с принудительной проверкой

Незнание в мире открытых исходников — это что-то паранормальное. Впрочем, для того, чтобы узнать ответ на этот вопрос, достаточно обычного strace. Надо использовать абсолютные пути и не очень древние версии PHP (statcache появился где-то между 5.1 и 5.2), тогда разница будет минимальна.

>> Свой профайлер, я настроил

А вот самое важное упомянуто только 1 раз и косвенно.

Напоследок дам новичкам один совет, который перекрывает все вышесказанное:

поставь opcode cacher, дубина!
и действительно, какие еще могут быть require и include на высоконагруженных проектах )))
поддерживаю Вас
Склеивание ZF в двухмегабайтный блоб, тоже не highload, хотя многим нравится.
Откуда вы знаете, куда записывают в приличном обществе?
С вашей аргументацией, могу сказать лишь «привет, коллега!».

«Ага, в рамках государственной инновационной программы воспитываем нанооптимизаторов.»
Да, понимаю, вам наноденьги попилить не дали, негодуете?

«У нас тут, представляешь, многозадачные системы щас, и между file_exists и include может произойти что угодно.»
Ну расскажите, что же может произойти?

«А вот самое важное упомянуто только 1 раз и косвенно.»
Профайлер, это не что-то очевидное, а?

«На миллионе итераций разница в пределах погрешности измерения.»
Чем эта фраза менее гуманитарна моей?

«Более. За одну трату рабочего времени на такие «оптимизации» надо увольнять нахер.»
Подозреваю, с таким уровнем диалога, максимум, кого вы увольняли, это кошку.

«Незнание в мире открытых исходников — это что-то паранормальное.»
Не смотрел в исходники, я наблюдение делал, а не исследование сырцов.

«За указания «это быстрее чем то» без приведения кода бенчмарков, условий, в которых они проведены, и результатов оных, в приличном обществе записывают в, ммм, гуманитариев.»
Вы топик читали? Я указал, почему нет абсолютных цифр.

«opcode cacher»
Это такая штука, которая помогает вам скрывать свой говнокод?
цифры нужны для оценки масштабов. что-то сильно помогает, а что-то безтолку менять.
> Это такая штука, которая помогает вам скрывать свой говнокод?

Мдааааааааааааааааааааааааааааа…

Сходите, уважаемый, в гугл, и прочитайте, что такое opcode cacher. Подсказка — это не Zend Optimizer, подсказка 2 — это и не ioncube.

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

Про apc, xcache, eaccelerator и.т.п, не вам, и не мне рассказывать.
Погуглили, отлично. Теперь погуглите, например, по strace :)
Я знаю что такое strace, тут не гуглить можно, а man в родной консоли набрать, если вы понимаете, о чём я.
Интересно. В статье не сказано и слова про оптимизацию (может правда уже убрали это), но все видят в этой информации только это. Чего плохого в том, если будет знать человек эти подходы и использовать их сразу при написании кода? И тогда, может быть, сервера апгрейживать надо будет не сегодня, а послезавтра.
Вот именно в этом и проблема. Что из этой статьи делается вывод, будто «эти подходы» имеют хоть какое-то отношение к апгрейду сервера.
И не было там слова «оптимизация».
Мне непонятна критика. Если эта статья не про оптимизацию, то почему её все тут стали упоминать с возгласами типа «Так нельзя оптимизировать».
Потому что, чтобы срать в комментах, топик-то читать необязательно =)
Потому что «сделать что-нибудь такое, чтобы сервера не пришлось апгрейдить» — это и есть оптимизация. То есть вы тоже восприняли эту статью именно так. Другого-то смысла у нее и вовсе нету.
Я под оптимизацией понимаю это: есть код, изменяем его и получаем более быстро работающее приложение. А вот как называется процесс написания кода с использованием знаний о том какие конструкции работают быстрее — я не знаю.
Прочитайте книгу Стива Макконнелла «Совершенный код». Там дается ответ на этот вопрос.
«преждевременная оптимизация» :)
Не силён в подобной терминологии. Но пока ел арбуз то немного помедитировал на него. Оптимизация — это процесс изменения кода с целью улучшить (а в частности убыстрить) приложение. — Вот такой мой взгляд на этот термин. Другими словами для оптимизации код уже должен существовать.
Тогда в моём понимании «преждевременная оптимизация» — это процесс изменения гипотетического кода с целью улучшить будущее приложение. Ну, а, если я сразу знаю, что задача А решается подходом Б, то тут нет речи об изменении кода, гипотетического или реального.

А, вообще, это термин «преждевременная оптимизация» очень странный. Вот есть рефакторинг — это тоже изменение существующего кода (но с другими целями), но вот термина «преждевременный рефакторинг» не слышал.

Да и потом, вычисления длинны массива перед циклом Вы же не назовёте «преждевременной оптимизацией». А как Вы это назовёте?
Именно так и назову. Потому что это она, родимая, и есть.
А насчет странности термина — это не к нам. Это к старику Кнуту, о котором флейм выше.

По поводу «JSON vs XML»: в Symfony для хранения конфигурации используется YAML. Я попробовал использовать YAML в отдельном проекте — мне понравилось. А для человека, незнакомого с программированием, читается на порядок легче, чем XML или JSON.

В качестве парсера для YAML использовал Spyc.
Если уж говорить о производительности, то .php с массивом — идеал (сляжет в opcode cache сразу). Можно в него компилировать при необходимости :)
Уже выше обсуждалось, что конфиги и код, имеет смысл разделять.
А где я сказал, что их не надо разделять?
Разделять не по файлам, а по инфраструктуре.
И что же мешает?
Прочитайте комменты.
пхп код проигрывает по читаемости и уровню входа.
YAML не из коробки, потому и забыл, хотя формат хороший.
YAML вещь отличная, но Spyc – страшно медленная штука. Расширения php_yaml или php_syck из PECL быстрее во много раз.
НЛО прилетело и опубликовало эту надпись здесь
Но если ваш junior developer, не хочет признавать их важность, расскажите ему, что на генерацию одного notice у PHP уходит время, за которое можно обойти и инкрементировать массив из примерно 30-ти элементов.

В этом вся суть junior'ов и статей, которые они пишут :)
Наплевать, что делаем что-то не то и с ошибками. А вот псевдооптимизация это важно.

Публикации