Евгений Степанищев

Я — эксперт в области разработки веб-приложений и безопасности в интернете. Каждый месяц мой блог посещают около 90 тысяч человек. Работаю техническим директором в «Системах документооборота», занимаюсь электронным правительством.

Habr, WTF?

Хабр не устаёт меня удивлять всё снижающимся качеством статей и кода. Ну вот что это:
    if(strpos($name, 'fetchRowBy') === 0) {
      array_unshift($arguments, substr($name, 10));
      return call_user_func_array(array($this, 'fetchRowBy'), $arguments);
    }
Ещё бы регулярное выражение использовал, ей-богу!
21 июля 2008 10:14

Азат Разетдинов (razetdinov.ya.ru)
21 июля 2008, 12:06

substr($name, 0, 10)?

Артём Курапов (kurapov.name)
21 июля 2008, 12:20

сервак не отвечает, хм

bolk (bolknote.ru)
21 июля 2008, 12:31, ответ предназначен Азат Разетдинов (razetdinov.ya.ru):

strpos($name, 'fetchRowBy') === 0

bolk (bolknote.ru)
21 июля 2008, 12:31, ответ предназначен Артём Курапов (kurapov.name):

Хабр?

jimidini (jimidini.ya.ru)
21 июля 2008, 12:59, ответ предназначен bolk (bolknote.ru):

а что не так с strpos? это самая эффективная проверка
substr() менее эффективен из-за дополнительной аллокации памяти под строку

bolk (bolknote.ru)
21 июля 2008, 13:03, ответ предназначен jimidini (jimidini.ya.ru):

substr_compare

FX Poster (blog.fxposter.org)
21 июля 2008, 13:16

Код не мой, я просто разместил его. :)

На самом деле - этот кусок был взят <a href="http://svn.symfony-project.com/plugins/sfPropelFinderPlugin/lib/sfPropelFinder.php">отсюда</a> (ctrl-c/ctrl+v, бездумно практически :)), и это, по-моему единственное, что делал не я, а Женя тут придирается. :)

Да и вообще:

<pre><code class="php">strpos($name, 'fetchAllBy') === 0)
substr($name, 0, 10) === 'fetchAllBy'</code></pre>

На небольших строках разницы не вижу, а методов длинной в 10k символов я не видел. :)

FX Poster (blog.fxposter.org)
21 июля 2008, 13:17

Жень, добавил бы сюда поддержку html, что ли :)

bolk (bolknote.ru)
21 июля 2008, 13:18, ответ предназначен FX Poster (blog.fxposter.org):

Нафига тут HTML? :)

bolk (bolknote.ru)
21 июля 2008, 13:19, ответ предназначен FX Poster (blog.fxposter.org):

Не видишь разницу? :) Представь, что у тебя 10k раз это вызвалось, теперь разница заметна? :) Всякую фиговину в вебе надо представлять внутри ещё одного внешнего цикла, который создают пользователи.

FX Poster (blog.fxposter.org)
21 июля 2008, 13:23, ответ предназначен bolk (bolknote.ru):

Представь, что у тебя 10k раз это вызвалось, теперь разница заметна? :)
Надо проверить ;)

david-m.livejournal.com (david-m.livejournal.com)
21 июля 2008, 13:44

substr_compare

Люблю, блин, php. Можно на нём десять лет писать, и всё равно новая функция где-нибудь вылезет.

david-m.livejournal.com (david-m.livejournal.com)
21 июля 2008, 13:52

Так, специально для любителей экономии на спичках. Миллион (!) оборотов цикла:

$str = "fetchRowByName";
$pref = "fetchRowBy";
$preflen = strlen($pref);

(strpos($str, $pref) === 0) — 0.45 сек
(substr($str, 0, $preflen) == $pref) — 0.68 сек
(substr($str, 0, $preflen) === $pref) — 0.55 сек (! — хозяйке на заметку)
(substr_compare($str, $pref, 0, $preflen) == 0) — 0.84 сек

FX Poster (blog.fxposter.org)
21 июля 2008, 14:05, ответ предназначен bolk (bolknote.ru):

Ну вот, уже проверили :)

bolk (bolknote.ru)
21 июля 2008, 14:48, ответ предназначен david-m.livejournal.com:

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

bolk (bolknote.ru)
21 июля 2008, 14:48, ответ предназначен FX Poster (blog.fxposter.org):

Неправильно проверили.

bolk (bolknote.ru)
21 июля 2008, 14:49, ответ предназначен david-m.livejournal.com:

Из-за «экономии на спичках» AdMe.ru хорошо работает на довольно среднем железе (у меня на предыдущем месте работы десктоп был мощнее того сервера).

arty (arty.name)
21 июля 2008, 14:49, ответ предназначен david-m.livejournal.com:

в тесте не учтен случай с длинными строками, не содержащими префикса ; )

bolk (bolknote.ru)
21 июля 2008, 14:49, ответ предназначен david-m.livejournal.com:

Так мануалы надо читать :)

bolk (bolknote.ru)
21 июля 2008, 14:52, ответ предназначен FX Poster (blog.fxposter.org):

http://ez.no/fr/content/download/134087/853115/version/2/file/ez2006_high_perfromance_php.pdf

Кстати.

bolk (bolknote.ru)
21 июля 2008, 14:58, ответ предназначен david-m.livejournal.com:

Кроме всего прочего, надо всё это запустить несколько раз и подсчитать среднее.

david-m.livejournal.com (david-m.livejournal.com)
21 июля 2008, 14:59

$str = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.";
$pref = "fetchRowBy";

(strpos($str, $pref) === 0) — 0.67
(substr($str, 0, $preflen) === $pref) — 0.58
(substr_compare($str, $pref, 0, $preflen) == 0) — 0.82

Ещё что-нибудь?

bolk (bolknote.ru)
21 июля 2008, 15:09, ответ предназначен david-m.livejournal.com:

Версия PHP?

Видимо, Ilia Alshanetsky должен обновить свой документ.

Артём Курапов (kurapov.name)
21 июля 2008, 15:15

Да, хабр видимо в дауне был. Или с ДНСом у меня что-то не так.

Я бы использовал substr, и логичней и как показывает последний тест - побыстрей. Но скорость в таких случаях очень мизерная, ими можно принебречь на мелких проектах..
Пойду добавлять в http://kurapov.name/technology/web/php/php_speed/

bolk (bolknote.ru)
21 июля 2008, 15:32, ответ предназначен Артём Курапов (kurapov.name):

Я мелкими проектами уже много лет не занимаюсь, так что со своей колокольни сужу. Ни и во framework'ах надо аккуратнее быть — неизвестно в каких проектах они будут использоваться.

FX Poster (blog.fxposter.org)
21 июля 2008, 15:59, ответ предназначен bolk (bolknote.ru):

http://ez.no/fr/content/downlo…romance_php.pdf
>
Objet non disponible
L'objet que vous avez demandé n'est plus disponible pour le moment.

Выложи где-нибудь?

FX Poster (blog.fxposter.org)
21 июля 2008, 16:07, ответ предназначен david-m.livejournal.com:

$str = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.";

Такого метода быть не может ;)

fim (fim.ya.ru)
21 июля 2008, 17:51, ответ предназначен FX Poster (blog.fxposter.org):

Может быть оно?
http://ilia.ws/files/frankfurt_perf.ppt

Owner (companyowner.myopenid.com)
21 июля 2008, 18:25, ответ предназначен david-m.livejournal.com:

Полностью согласен. Это кстати общая тенденция большинства "geek"'ов, которую приходиться отучать, чтобы другие члены команды не страдали. Понапишут развёртавыемые циклы и функции по 1000 строк с названием "mtzv" и гадай потом что да как. Одна из главных целей в любом продукте - это лёгкость в поддержке, если код понятен, легко расширяем, значит направление верно. Из моего опыта в 90% случаях ботлнеками являются совсем другие вещи, чем мусоличть доли секунд при обработке миллиона операций.

Конечно, это всё относительно и дополнительные поблажки могут быть добавлены для малых проектов (команда 2-3 человека), но когда команды 5 человек и более и разработка идёт по agile, то надо интегрироваться в команду а не являтся её тормозом и переписывать работающие куски из-за того, что он работает на 0.05сек медленее
при 1m операций. Любой мэнеджер убил бы за такое. :)

По поводу железа... благо нынче он достаточно дешовое и тот же quad-core с несколькими гигабайтами памяти можно купить за приемлимые деньги (а уж тем более для тех кто планирует заниматься рекламой).

bolk (bolknote.ru)
21 июля 2008, 19:00, ответ предназначен FX Poster (blog.fxposter.org):

Это известный PDF Ilia Alshanetsky об оптимизации PHP, он его каждый год выпускает, в инете сотни копий.

bolk (bolknote.ru)
21 июля 2008, 19:02, ответ предназначен Owner (companyowner.myopenid.com):

О покупке часто речь не идёт. Выделенные сервера довольно часто *арендуются*. Это даёт массу плюсов при выходе оборудования из строя (к примеру, на adme винты летят от нагрузки раз в полгода).

Аренда хорошего сервера — это совсем уже другие деньги. Иногда, существенные, особенно, если арендуется не один сервер.

У меня тоже очень большой опыт устранения bottle necks, причём вполне успешный. Последние несколько лет я непрерывно, иногда в реальном времени занимался нагруженными и быстрорастущими проектами.

bolk (bolknote.ru)
21 июля 2008, 21:22, ответ предназначен Owner (companyowner.myopenid.com):

Вы кстати, сейчас применили троллевский приём: приписать оппоненту какое-то действие и осудить его. Не нужно так делать.

david-m.livejournal.com (david-m.livejournal.com)
21 июля 2008, 22:32

Виноват, отходил. Версия PHP 5.2.0 (cli) под win32. Вообще, проверье сами, это же несложно:

<?php
$str = "fetchRowByLorem";
$pref = "fetchRowBy";
$preflen = strlen($pref);

$t =- microtime(true);
for($i=0;$i<1000000;$i++) {
(strpos($str, $pref) === 0);
//(substr($str, 0, $preflen) === $pref);
//(substr_compare($str, $pref, 0, $preflen) === 0);
}
$t += microtime(true);
echo $t."\n";
?>

Вообще, по моему опыту «спичечной» оптимизации php-кода, тормоза возникают в основном в интерпретируемом коде. То есть, библиотечные функции сами по себе работают очень шустро, но лишнее присваивание или лишняя переменная (в PHP-коде) в цикле может сильно просадить скорость. И второй момент — библиотеки в PHP тоже написаны… довольно фиговенько. Даже если есть специальная функция под какую-то задачу, _обычно_ гораздо шустрее бывает использовать более простую функцию, реализующую какой-нибудь классический алгоритм. Как здесь — поиск в строке. Это старая функция, явно использующая какой-то стандартный сишный код, поэтому я бы априори ожидал, что она будет самая скоростная. Так оно, в общем, и оказалось. Substr сам по себе мог бы быть ещё шустрее, но тут наружу надо доставать результат и сравнивать его уже в PHP. Это замедляет.

Так что, по-моему, в исходном коде гораздо больший потенциал «спичечной» оптимизации содержится во второй и третьей строках. Но искать альтернативы и проверять лень:)

Что касается последнего теста — вспоминаем специфику задачи. Там _всегда_ будут короткие строки.

bolk (bolknote.ru)
22 июля 2008, 09:12, ответ предназначен david-m.livejournal.com:

Да я уже проверил. Зачем в вашем коде «$t =- microtime(true)»?

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

Кстати, сколько прогонов перед усреднением вы делали?

Owner (companyowner.myopenid.com)
22 июля 2008, 11:28, ответ предназначен bolk (bolknote.ru):

Не совсем понятно причём тут "троллевский приём", ну да ладно... я просто высказывал свою точку зрения и делился своим опытом.

bolk (bolknote.ru)
22 июля 2008, 12:54, ответ предназначен Owner (companyowner.myopenid.com):

Я же расписал какой именно приём применён.

david-m.livejournal.com (david-m.livejournal.com)
22 июля 2008, 13:01

Да я уже проверил. Зачем в вашем коде «$t =- microtime(true)»?
В смысле, зачем? Чтобы float получить.

Кстати, сколько прогонов перед усреднением вы делали?
Прогонял раз по несколько. Это на домашней машине, она ничем другим не занималась, так что результат был стабильным ± единички во втором знаке.

5.3 — да, скорей бы уж.

bolk (bolknote.ru)
22 июля 2008, 14:49, ответ предназначен david-m.livejournal.com:

«-=» зачем.

david-m.livejournal.com (david-m.livejournal.com)
22 июля 2008, 15:31, ответ предназначен bolk (bolknote.ru):

$t =- microtime(true);

$t += microtime(true);

Для красоты внешнего вида, исключительно:)

Ваше имя или адрес блога (можно OpenID):

Текст вашего комментария, не HTML:

Кому бы вы хотели ответить (или кликните на его аватару)

Подсказка по написанию комментария

В комментариях можно применять следующую специальную разметку:

  • слово, обрамлённое в «звёздочки» выделяется *жирным*
  • ссылка становится ссылкой: http://bolknote.ru
  • ссылка в скобках также становится ссылкой, закрывающая скобка не захватывается: (http://bolknote.ru)
  • каждую строку цитаты следует начинать со знака «больше»:
    > это цитата
    > из двух строк
  • можно вставить картинку, залитую на один из сервисов: «Яндекс.Фотки», «Фликр» или «Пикплз». Для этого нужно вставить на страницу полный адрес вашей картинки на сервисе, он превратится в картинку:

    http://fotki.yandex.ru/users/bolknote/view/274311?page=3