Pull to refresh

Comments 147

> Разбивайте программу и любой _блог_ на инициализацию, настройку...
:)

Хорошая статья. Спасибо.
спасибо =)) а почему lighthtppd ??? а не nginx ???
а если у меня несколько fcgi-backend??? да еще и на удаленных машинах (пресловутые tcp сокеты?? ;) ?
почему бы и нет? В lighttpd можно балансировку нагрузки по нескольким fcgi-серверам парой строчек сделать, см. доки.
nginx мне тоже более симпатичен, поэтому держите плюсь, но lighttd ни в чём ему не уступает.
:) Нам nginx очень помог своим ngx_http_memcached_module. Это действительно оказалось очень удобным и быстрым, при условии адекватной генерации линков и ключей. Борьба с персонализацией осуществляется генерацией $memcached_key исходя из ngx_http_userid_module-вского $uid_got.
Весьма интересно было почитать :)
отлично! Очень полезно для того, кто учит PHP по манам. Спасибо.
Хороший материал, молодца!
P.S. Сам когда-то одной рукой писал, причем левой, так что памятник тебе :))
UFO just landed and posted this here
Передача переменной по ссылке (например $a=1; call_func(&$a)) - не влияет на быстродействие. Передача массивов по ссылке - влияет чуть-чуть. Передача классов - влияет очень.

Видимо все-таки передача объектов, а не классов. А есть результаты тестов подтверждающих это? В PHP5 переменные-объекты являются ссылками на структуры в памяти, так что передача по значению не может тормозить. Непонятно так же почему в PHP4 передача объектов "тормознее" передачи массивов. У меня воспроизвести это не получилось.
Ну и конечно это имеет смысл только если сами передаваемые массивы/объекты не изменяются внутри функции, так как задействуется механизм отложенного копирования.
В PHP5 объекты вообще по значению не передаются, если нужна копия, вызывают clone.
Переменные, содержащие объекты передаются по значению, но этим значением является ссылка. Передача же по ссылке (с &) означает передачу по ссылке самой переменной (имени переменной). Может я сейчас несколько напутал с терминами, но вот пример:
function func(x) {
x = 1;
}
obj = new Class();
func(obj); // С самой переменной obj ничего не произошло.
func(&obj); // А теперь в ней единица.
function func($x) { $x->value = 1 }

$obj = new stdClass();

func($obj);

у obj появится свойство value со значением 1, вот что означает, что в PHP5 объекты передаются по ссылке.
Отнюдь. Это значит, что передается по значению ссылка на объект. Изменение содержимого объекта затрагивает и глобальную переменную, т.к. она ссылается на ту же структуру в памяти, что и локальная. Однако, заменить для переменной один объект на другой не возможно, как я показал выше.
"Передаётся по значению ссылка на объект" это и означает, что "объект передаётся по ссылке". Не переменная $x передаётся по ссылке, а объект.
Это уже вопрос терминологии. Все-таки в PHP под "передачей по ссылке", обычно понимают передачу имени переменной. И "передача объекта по ссылке" многих вводит в заблуждение в понимании механизмов. Одно из различий м/у двумя этими понятиями я указал — различное поведение при записи нового значения в переменную. Для многих это становится неожиданностью.
Кто понимает? Где понимает? в выражении $a = new stdClass() что передаётся по ссылке? имя? или всё-таки объект?
Передается переменная. Значение переменной. Которое является ссылкой. Объект не передается никуда. Объект лежит себе где-то в памяти и ему глубоко все равно, какие переменные на него ссылаются в каких количествах и куда эти самые переменные передаются.
Переменная - такая же область памяти. Имя - это всего лишь имя, у области памяти их может быть сколько угодно.
"Передача по имени" и "по ссылке" — расхожие термины. И говорят о передаче именно значения, а не её ссылки.

Если у вас выработалась другая терминология, должная, на ваш взгляд, заменить прежнюю — напишите об этом статью, аргументируйте, будет полезно.
А я от терминов и не отхожу.
Будет карма и время, обязательно напишу.
Пардон, в выражении "$a = new stdClass()" ничего никуда не передается. В нем создается структура объекта в памяти, создается значение переменной, ссылающееся на нее и создается имя переменной в данном контектсе, ссылающееся на значение переменной, ссылающейся на структуру в памяти.
выражение $a = &new stdObject() в PHP4 вам знакомо?
Мы не о PHP4 говорим. В PHP4 с этим заморачивались из-за того, что "new stdObject()" создавала объект в качестве значения, после чего происходило присвоение, т.е. копирование всего объекта. Теперь же результатом "new stdObject()" является не сам итоговый объект, а ссылка на него, которая и становится значением $a.
За деревьями не видите леса. Это стало следствием того, что объект передаётся по ссылке. Он и вернётся по ссылке и в функцию попадёт по ссылке.
Пардон, сейчас о PHP4 или о PHP5?
Передача "по значению" или "по ссылке" указывает на то, как локальная переменная вызванной функции, соответствующая аргументу, связывается с переменной из контекста вызывающей. При передаче по значению - никак. При передаче по ссылке, они становятся ссылками на одно значение.
Про отличие PHP4 от PHP5.

Именно. Они и становятся ссылками на одно значение.
И остаются при присваивании локальной переменной нового.
При передаче же по значению, присваивание нового значения локальной переменной никак не затрагивает исходную, вне зависимости от того, какого типа было значение.
Пример с "$x->value = 1" к этому не относится, т.к. здесь $x резволится в объект, с которым уже и выполняются последующие действия (присвоение свойства).
Я, кажется, понимаю вашу точку зрения. Но ссылки в PHP имеют массу особенностей в поведении, ваша терминология позволяет их объяснить?
Да, нет, я и не пытался особо вводить новые терминологии и что-то объяснять :).
Я просто выразил недоумение по поводу информации приведенной в статье.
deprecated
надо так
function func(&x) {
x = 1;
}
Большое спасибо. Наконец то серьезно написали об оптимизации.
Стандартный механизм сессий бы еще в "...о возможных тратах...", а то уж больно тормозной он
Обработка тонны require_once и include_once
Решение "влоб" нашлось само собой

А решение не в лоб, а в глаз — использовать автоподгрузку (в общем случае __autoload).
не вариант. Время тратится не на парсинг строчки require в файле, а на заглядывание в файловую систему, просмотр mtime файла и тп. Поэкспериментируйте =).
Время тратится на подключение файла. Тянуть 300 файлов на каждый чих — не лучший момент в ZF.
__autoload работает медленее явных require_once, include_once. Проверено опытным путем.
Хм. Конечно, 300 прерываний на автолоад с его обработкой будут медленнее трехсот require, тем более, что в автолоаде в итоге приходится тот же самый require и вызывать. Только смысл то его именно в том, чтобы сократить количество подключений. Иногда оно сокращается во много раз.
А почему APD, а не xdebug? Есть какие-то нарекания к последнему, или просто, что первое под руку попалось?
нареканий нет. Просто всё что в PECL и ставить проще и не подводило оно никогда. Да и попадает оно туда не просто так. Тем не менее я не в курсе есть ли у xdebug профилер или нет.
sudo pecl install xdebug-beta

Профайлер есть, создает в cachegrind:
xdebug.profiler_enable = 1
xdebug.profiler_output_dir = "/tmp/php"
попробую встретится с ним второй раз, хорошо.
не ясно преимущество использования лямбда-функций при обходе массивов, ведь код в create_function будет интерпретироваться во время выполнения и не попадет в кэширующий механизм.
Код, похоже, оптимизируется, хоть и не кешируется. Я делал замеры быстродействия eval vs create_function, последняя конструкция работает явно быстрее.
<?php $a=array('a'=>1,'b'=>2,'c'=>3);
$t=microtime(1);for ($i=0;$i<=1e5;$i++) foreach ($a as $k=>$v) $tmp=$k.$v;echo (microtime(1)-$t)."\n";
$t=microtime(1);for ($i=0;$i<=1e5;$i++) foreach ($a as $k=>$v) eval('$tmp=$k.$v;');echo (microtime(1)-$t)."\n";
$t=microtime(1);for ($i=0;$i<=1e5;$i++) array_walk($a, create_function('&$v,$k', '$tmp=$k.$v;'));echo (microtime(1)-$t)."\n"; ?>

Результат:
0.26393890380859
4.604434967041
4.8136839866638

простой foreach быстр, create_function и eval сравнимы, и array_walk добавляет некоторую задержку.
Какой кеш кода вы использовали?
eaccelerator, но вообще это это не имеет значения, т.к. при выполнении скрипта в консоли результаты примерно те же. этот тест не кеширующего механизма, а интерпретатора пхп, кеширование пяти строк 300000 итераций мало что даст.
eaccelerator, помимо кеширования, делает ещё и оптимизацию. Значит что-то изменилось в датском королевстве, раз eval стал примерно равен create_function на eaccelerator.
вполне логично, что их эффективность примерно одинакова, в обоих случаях производится интерпретация и выполнение непредсказуемого кода
Конечно логично, но факт остаётся фактом — около 1.5 года назад разница в скорости была существенной.
уже умудрился разогнать ваш пример в почти 100 раз - вынеся create_function вверх (какой смысл её столько раз запускать делая одно и то же?).

Про лямбда-функции, каюсь, я не имел ввиду здесь разгон в скорости (создание какой-нибудь простой фунции будет быстрее), но выглядит куда понятнее.

1,'b'=>2,'c'=>3);
$lfunc = create_function('&$v,$k', '$tmp=$k.$v;');

function z(&$v, $k) {
}

$t=microtime(1);for ($i=0;$i$v) $tmp=$k.$v;echo (microtime(1)-$t)."\n";
$t=microtime(1);for ($i=0;$i

результат:
mocksoul@home ~ $ php t.php
0.258806943893
0.515441179276
0.274258108139
Спасибо, интересно почитать.
Конечно, есть и вопросы, например, почему LigHTTPd, а не nginx?
Opcode Cacher? Xcache? :)
nginx менее production-grade. Хоть и чуть шустрее чем lighttpd, но куда менее гибок и удобен в настройке. Имхо.
А приведите пример, пожалуйста, почему Вы так считаете ?
UFO just landed and posted this here
если мне не изменяет мой склероз, то Игорь рассказывал о неком иностранце (который русского не знает), который по _русским_ докам легко смог настроить nginx.
UFO just landed and posted this here
1) У eaccelerator/xcache тоже есть функции для работы с shared memory, кроме того, они есть и в самом PHP — аж два модуля (shm_* и shmop_*). APC один из самых медленных кешей по тестам, кроме того, у него всё плохо с оптимизацией — глюков много.

2) не к чему писать столько 'disable' при компиляции PHP, зачем эта дикая строка? Например mSQL и MS SQL не собираются по-умолчанию.

3) Persistent connect к MySQL пока очень плохо работают с транзакциями (пока не вышел mysqlnd, где это поправлено должно быть). Кроме того, быстрее работает не PDO (и даже не mysqli), а стандартный старенький extension mysql.

4) по пункту 9 — sprintf не самая шустрая конструкция на земле, а интерполяции, конечно же, нет ничего дебильного.

5) по пункту 11 — PHP всегда передаёт переменную по ссылке и копирует её лишь в том случает, если её начинают менять (если конечно программист её сам по ссылке не передал).

6) совет №4 вообще страннен, классы надо делать статическими, если нужно, а не если можно.
1. shmop явно неудобен. На shm_* посмотрю, интересное замечание, спасибо
2. чтобы всё было подконтролем, в независимости от того что решат сделать дефолтным в следующей поставке php ;)
3. PDO_* работает конечно медленнее чем mysql, т.к. он является для него оберткой. С транзакциями в MySQL при постоянных подключениях есть одни огромные грабли - нужно в конце скрипта не забывать транзакции откатывать или коммитить. Потому что сам он этого делать уже не будет (т.к. коннект не рвётся)
5. Я в общем-то и написал "не пытайтесь ничего скоприовать по ссылке пока это действительно не будет необходимым" ;).
6. Просто на моих глазах было много программистов - которым уж очень нужно было всегда создавать экземпляры классов... Даже для factory делали.
3. ага, а любое действие, которое нужно "не забыть" - это уже ошибка, ибо должно делаться автоматом.
и, самое главное, нельзя полагаться на то, что выполнение вообще дойдет до вашего "не забытого" закрытия(commit/rollback т.е.) транзакции, т.к. скрипт может быть убит или самоубиться по разным, часто не зависящим от него причинам, сильно надежнее все же без pconnect жить.
я потестирую транзакции, возможно модель постоянных соединений в PDO_MYSQL работает несколько по-иному.
Это конечно, полагаться на то, что скрипт "доживёт" до конца в PHP — большая ошибка, не настролько он надёжен. Но проблемы с транзакциями на persistent (кстати, исключительно внутри хранимых процедур, если не ошибаюсь) с умиранием скрипта и забытыми коммитами не связаны.
не исключительно, транзакция будет висеть открытой пока соединение не закроется или timeout или commit/rollback.
а вот умирание скрипта с этим пожалуй не связано дествительно, ибо в случае умирания скрипта разницы между persistent и обычным не будет, тут я не совсем по делу да :)
3) PDO является обёрткой для MySQL API, так же как и mysql_* и mysqli_*. А транзакции, это, безусловно, совсем не грабли, иногда это необходимость (в некоторых случаях хватает и LOCK) и COMMIT/ROLLBACK надо делать не в конце скрипта, в конце транзакции. И проблемы связаны (увы) не с забытыми коммитами.
зато PDO позволяет малой кровью перейти, например, с PostgreSQL на MySQL. К тому же мне особо импонирует возможность параметризованных запросов (SELECT * FROM t1 WHERE foo = ?), чего нет в нативном mysql_*, и, как следствие, голова не болит о http request parameters escaping.
Вы, кажется, не поняли о чём я пишу — о некорректной работе транзакций с persistent connection. PDO вам не позволит перейти на PostgreSQL, если вы с самого начала не озаботились тем, чтобы использовать универсальный синтаксис.
вообще-то я про скорость PDO vs "стандартный старенький extension mysql". Выбирая между PDO и нативным extension, я выбираю PDO :-)
Тема этого поста — скорость, вот я и высказался. Так что, в плане скорости, я PDO не выбираю. Тем более достоинство одно — быстрая смена базы при **определённых условиях**.
Спасибо автору!
Одно добавление из моего личного опыта. У меня нет столько опыта, чтобы быть экспертом во всех областях. Поэтому я использую стандартные настройки сервера и программ, общие правила по написанию кода, не стараюсь добиваться максимальной производительности от функции. Два критерия хорошо кода - понятность и красота :) В результате 80% производительности определяется тем, как спроектирована система. Не бойтесь потратить ваше время на обдумывание и проектирования.
Категорически против.
Никогда не тратьте время на предварительное проектирование: в определенный момент разработка встает колом по причине "недостаточно проработанной архитектуры системы". Код должен сам говорить, где хорошо, а где плохо. TDD вам в руки. ;-)
TDD и отсутствие проектирования архитектуры не имеют между собой ничего общего. Всегда нужно сначала думать а потом делать, иначе ничего хорошего не выйдет. Практики TDD же позволяют сначала разрабатывать тесты, а уж потом писать для них код.

Не путайте молодёжь =)
Думать, безусловно, надо. Не надо много думать.

Согласитесь, мало найдется проектов объемом больше трех человеко-месяцев, которые, несмотря на изначальное подробное описание и проектирование "до последней кнопки", не вызывали бы ощущения общирного "костылизма" и мыслей "всю эту хрень переделать". Проектная документация, как правило, устаревает на полпути к дедлайну, после чего на нее (документацию) вообще забивают по причине нехватки времени ;-) Так что подробное проектирование дизайна системы в начале проекта обычно вредит самому проекту, потому что позже команда не может найти в себе силы перекроить дизайн. И чем больше проект - тем хуже результат. Я наблюдал это многократно в разных софтверных компаниях.

Спасти положение может либо рефакторинг, либо переделка "с нуля". А теперь скажите, какой рефакторинг возможен без TDD? Вы лично подпишетесь рефакторить систему с 2МБ пхп-шного кода без наличия тестов на код? ;-) Сила TDD как раз-таки в том, что использование TDD позволяет измененять дизайн системы (читай делать перепроектирование системы) без ущерба качества системы в тот момент, когда разработчик посчитает это нужным. Т.е. фактически не думать о проектировании "на потом". Ключевое слово в TDD рефакторинг.
я конечно не знаю - может вам заняться нечем вот вы и мусолите одно и тоже по десять раз... я лично был свидетелем проектов 12 девелоперов * 6 месяцев, 80% которых были описаны изначально. И что вы мне доказываете в чем сила TDD - когда я и сам это прекрасно знаю и ни в коем случае не ругаюсь на экстремальное программирование - даже наоборот =).

Была один раз задача - написать торрент-трекер, так если бы мы более 60% времени изначально не потратили на описание внутренней архитектуры и поиск проблем в зародыше - потратили бы уйму человеко-часов (слава богу, не своих) на их нахождение в процессе работы.
я с улыбкой все это пишу, не ссоримся! )))
Согласен с mocksoul. TDD и архитектура - разные понятия. Сравнивать нельзя. Касательно проектирования. Если нет четкого представления для чего, что должна делать программа и как этого достичь (я не говорю о расположении кнопочек), то программирование будет как парусник, у которого нет руля и управлять парусом нельзя. Плывем очень быстро, но сменился ветерок, и уже несемся в другую сторону. Мне это надо? Я все-таки получаю деньги за результат, а не за количество строчек и сколько раз я их переписывал. :)
В школе есть такое понятие как черновик и чистовик. Не знаю как сейчас, но раньше мы писали в черновик, что-то там правили, потом в чистовик. Ребенок пишет в черновик и знает, что можно делать не аккуратно и не сильно старается. Позже можно будет и исправить. Это же не чистовик. Не реальная жизнь – это чистовик. И делать надо сразу хорошо, исправить не всегда удается. Может быть поэтому, как вы пишите “Проектная документация, как правило, устаревает на полпути к дедлайну, после чего на нее (документацию) вообще забивают по причине нехватки времени”?
Дебилизм, столь часто употребляемый в статье, пишется через "е" ;)
хахаха рассмешил, спасибо =))) И правда.. чего это я...
Понторезный стиль изложения. Неприятно читать такие статьи.
Зато полно конкретики, а это как раз то, что ценно в данном случае. В отличие от обтекаемых рассуждений ведущего программиста Рамблера о highload-архитектуре на конференции, когда он толком ни на один вопрос не ответил.
насчет is_null - почти все подобные функции работают медленне
например empty работает на 10-15% медленне, чем просто if ($var).
ага, зато если у тебя неизвестно определена переменная или нет - ничего кроме isset'a не сможешь использовать - будет ошибка выполнения)
Вы не поверите, но isset - не функция, а конструкция языка, соответственно ее вызов не отнимает ни байта памяти.
о_О правда не знал) но спасибо ;)
С этим все часто путаются. Всегда имейте под рукой cheatsheet:
http://www.php.net/manual/en/types.comparisons.php
Вообще статья хорошая, особенно фраза "Увеличение быстродействия на 10% на 1 сервере даёт прирост в скорости равный 10%. А если у вас уже 10 серверов - то 10%-ое увеличение быстродействие будет равно добавлению ещё одного 11-го сервера."

Грамотный подсчет ;)
<?php

function increment( &$a, $k )
{

$a = $a + 1;
}

$arr = array();

for ( $i=0; $i<10000; $i++ ) {

$arr[$i] = $i;
}

$t1 = microtime( true );

//array_walk( $arr, 'increment' );
foreach ( $arr as &$a ) {

$a = $a+1;
}
$t2 = microtime( true );

print $t2-$t1;
print_r( $arr );

?>

foreach быстрее в 8-12 раз. И читаемость повыше для несложных манипуляций.
попробовал и ваш пример. Получилось в 3 раза. Ладно победили. array_walk аутсайдер, хоть и удобен в некоторых случаях (не меняет курсор в массиве и тп). Тем не менее многие другие функции array_* в пхп вообще сложновато без сноровки реализовать foreach-ем. Сортировку, например.
Согласен, функции array_* очень часто выручают и работают сильно быстрее, чем самописные аналоги. Поди не на php написаны :)
Ахринительно полезная статья. Искренне благодарен.
Автор молодец, что потрудился и написал много полезных вещей для php-программистов (начинающих и не очень), но позволю себе заметить, что со знанием принципа работы lighttpd+php+fascgi у него пробел.

PHP никогда не запускает много потоков в одном процессе, не умеет он этого (а если вдруг я не прав, и он умеет, то буду счастлив узнать - как этого добиться). min-procs и max-procs действительно нужно ставить в 1, но не потому, что sharedmem не будет иметь смысла, а потому что балансировщик нагрузки у лайти корявый. А так он запускает один головной php-процесс в специальном режиме, а тот плодит заданное количество процессов и занимается распределением запросов между ними. А sharedmem имеет смысл как раз при работе с несколькими процессами, для этого его и придумали. А вообще, php лучше запускать независимо от лайти под другим пользователем.

То, что у автора выделено красным цветом - антисовет! Не запускайте такое огромное количество php-процессов - это верный путь к DoS'у. 20-30 процессов - это предел (зависит ещё от железа). Если все они заняты, то скорее всего камень загружен под самое не балуйся, так что лучше пусть лайти 500 плюнет, а не нагнетает обстановку, ибо тогда даже админ в консоли не войдёт.
Автору рекомендую исправить.
эээ.. потоки php как раз умеет. И красным цветом я говорил про потоки но уж никак не про процессы. И балансировать нагрузку надо не такими вещами, а чем-то более гибким ;)

О том как добится чтобы пхп запускал потоки - см. bin-environment в предоставленном мной конфиге. И 128 потоков PHP - я забыл упомянуть - это для 8-ядерного сервера хорошо... =) Другими словами прочитав статью головой-то все равно думать надо. Это не HowTo.
Ну-ну :)
ps auxw | grep php
в студию.
мда. нокаут. Самое обидное - что я сначала действительно так думал =). Статью подредактирую, спасибо.
для линукса 2 понятия такие как поток и процесс являются тождественными. или я ошибаюсь?
Ошибаетесь, это две большие разницы.
Статья может ввести в заблуждение.

По поводу: LigHTTPd, ну кому что, но зачем его-то?
1-й пункт: нужно применять там где нужно обычные вызовы, там где нужно _once. При чем тут оптимизация?
2-й пункт: практически никогда array_walk не будет быстрее языковых конструкций. Да и читаемость ужасная.
3-й пункт: Передавайте по ссылке то, что нужно передать по ссылке. При чем тут оптимизация.
4-й пункт: Вредный совет. Статические классы спецефичны и заменить обычные классы полностью или даже частично не могут. Применяются там, где нужно.
5-й пункт: На счет комментариев... При чем тут оптимизация. Комментарии просто нужны и лучше напишите их больше, чем меньше.
6-й пункт: Рекурсии... Что так тормозят? Иногда архиполезно...

С 9-м пунктом согласен кроме sprintf. Хотя иногда удобно ее использовать.
12-й да.

На счет кеширования обсуждалось.
Статья спорная и может ввести в заблуждение новичков.
кто-то находит полезным, кто-то вредным. Мнение субъективно по своей сути =).

Многое я писал для того чтобы наоборот не пытались оптимизировать там, где ничего не получится (передача по ссылкам). Заменять обычные объекты статичными (или по крайней мере сильно стараться это делать) - глупо. Я писал о том, что просто забывать о статических классах не стоит. По поводу комментариев - опять же слышал несколько мнений в виде "файлы должны быть маааленькими и комментарии тормозят парсинг" (абсурд, но не все это понимают). Рекурсии полезны, но если можно обойтись без них - лучше без них. Тем более учитывая что рекурсия без проверки вложенности может когда-нибудь вызвать segfault при перегрузке стека php. Sprintf в строках я дал опять-таки для примера, чтобы просто не забывали о его существовании ;).

Поймите - это не howto, это просто мысли в слух. Для каждого конкретного случая можно вспомнить что то из этой статьи а потом подумать "стоит это тут использовать или нет". Делать бездумно - глупо впринципе.
Я не говорил, что вредно. Всегда полезно! Вводит в заблуждение просто слово "оптимизация". Ну да ладно.
Единственное осталось что не понятно. Почему же рекурсия плоха? Замечательный инструмент. Конечно нужно быть осторожным при возможности зацикливания, но отказываться из-за этого нельзя.
например. обход дерева файлов при помощи виртуального курсора будет кушать памяти гораздо меньше чем с рекурсией. Сравню и покажу пример на досуге. Увидите :).
чтобы отключить все ненужные модули при сборке php, достаточно

--disable-all --without-all --disable-reflection

и дальше указать необходимые --enable и --with
не поверите - а просто так! =)
Огромное спасибо! Как говорят, "Чтобы стать профессионалом, всегда нужен учитель".

Жду продолжения/развития, так как с кэшем как раз мало практики.
«жду развития»

сильно сказано)) книги\гугл и развивайся на здоровье :)
Вы бы рекомендации APC убрали — самый тормозной кеш, даром что в PECL входит, а более быстрые конкуренты точно так же работают с shared memory (кроме ZO).
а Вы что используете?
Сейчас на одно сервере стоит xcache, на втором — eccelerator.
"сильно тормозной" это всё-таки слишком сильно сказано за xcache

за xcache http://www.dailymotion.com/blog/video/37… - далеко не всегда он аутсайдер. Да и вообще разброс по скорости там не настолько критичен =).

Разве что xcache надо пробовать. Это да.
Всё возможно. Я APC пробовал несколько раз, всегда снимал из-за глюков при включении оптимизации (в основном, у нас нагруженные, сложные проекты, поэтому глюки проявляются быстро), видел несколько benchmarks, результаты везде не в пользу APC, в первый раз вижу, чтобы APC настолько близок к лидерам был.
ну у них в доках сказано "ни за что не включайте оптимизацию - глючит!" =)) Сам пару часов затылок чесал при виде разваливающегося проекта ;). Но без оптимизации - как часы.

eAccelerator мне совсем не нра из-за непрозрачной архитектуры (лениво в исходниках копаться и рассматривать что же они там творят и API глядеть для PHP).. а вот xcache - растёт. Последний раз когда глядел на него - он в альфе был. Сейчас вроде как 1.2 уже. Надо ставить и пробовать. Да =).
UFO just landed and posted this here
Отличная статья.
Два года уже об оптимизации ни чего не слышно было.
Это в рунете ничего не слышно. В интернете постоянно пишут. Посмотрите, например, слайды by Ilia Alshanetsky
Огромнейшее спасибо! Прекрасная статья, однако для новичка сложновато будет...
Дал своим прогерам прочитать. Им понравилось.
А вы где работаете?
работаю с французами, сам с собой и ещё с партнёрами в россии... где конкретно - корпоративная тайна. А что есть какие-либо предложения? =))
> unix-сокеты много шустрее чем tcp-сокеты.

unix-сокеты *чуть-чуть* быстрее tcp.

> Opcode Cacher. Или кешер байткода. Или "что за дибилизм - парсить одни и те же файлы при каждом запросе?!". Очень (ОЧЕНЬ!) рекомендую APC (Alternative PHP Cache) который лежит в PECL. Можно так же eAccelerator или даже ZendOptimizer.

Вопиющая безграмотность - ZendOptimizer это не "кэшер байткода".
ZendOptimizer обладает этой функциональностью. Так? Лишь бы ляпнуть, честное слово.
unix-сокеты... а вы потестите, потестите... скорость установки соединения, нагрузка на ядро при большом кол-ве соединений, использование буфера (не перемешивающегося с буфером tcp)... вот и будет вам "чуть чуть" ;)
ZendOptimizer НЕ обладает этой функциональностью. Прежде чем писать статьи, ознакомьтесь с материалом, о котором пишете.

AF_UNIX сокеты на Linux, про который вы пишете незначительно быстрее чем AF_INET, даже на больших нагрузках. Это касается и скорости установки соединений (роутинг локальных tcp соединения в линуксе происходят через отдельную таблицу local) и скорости работы. Почему Вы считаете что ядро писали идиоты ? Вы сами тестировали ?
вы ошиблись и воинственно реагируете - а это не красит ;) ошиблись просто перепутав - опкод кеширует не оптимайзер, а zend platform (ранее zend accelerator)
в том то и дело - что я ошибся не в указании банковского счета (что действительно испортило бы мне настроение) - а всего на всего в названиях программ - и к таким замечаниям вроде "ох! это вопиющая безграмотность!" отношусь с должным сарказмом =). Zend Platform, так Zend Platform, каюсь, перепутал, подправлю статью.
Я извиняюсь, что так через стока времени тут возникаю, но — статья не подправлена, кажись, ни по одному из пунктов, по которым Ваше обещание подправить проскользнуло в комментах. Вы окончательно на это забили? И не появилось ли у Вас новых соображений? Тема-то всё ещё весьма актуальна, и на статью ссылаются. (За неё большой респект Вам!)
вау =)

за прошедшие два года многое изменилось… я больше не пишу вообще, целиком ушёл в мир Python/C/D. Увы, сейчас все мои эти танцы с бубном вокруг PHP кажутся детским садом — если в идеологию программного языка или платформы не вложена скорость/удобство — лучше и не пытаться это привить на верхних слоях.

И содержание блока «Зачем это всё?» уже совсем не отражает моё состояние =). Проекты надо делать такими, которые могут выдержать даже если вдруг завтра придёт в 1000 раз больше пользователей чем сегодня. И если об этом задумываться в самом низу (о чём, увы, в PHP думали не много) — то это перестаёт быть такой уж сложной проблемой. Всего-то надо не обогревать атмосферу тонной никому не нужных конструкций =).

Тем не менее мнение о PHP осталось сдержанно-холодное, но не гневное. Я правда не могу придумать себе сейчас такую задачку, в которой мой выбор пал бы снова на него, но зато глядя на него можно увидеть действительно потрясающий питон =)))))) Не было бы сравнения — не получилось бы))
UFO just landed and posted this here
Работа полезная, спасибо.

В таком решении на ряду - слитно?
и закрывающая скобка в примере с array_walk
Здравствуйте,

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

Странно, что Хабрахабр не пускает мое сообщение как комментарий. Видимо, оно слишком длинное - получилось 18 пунктов. :) Так что простите меня за саморекламу, но, видимо, придется писать в свой блог и давать ссылку. :)

http://karellen.habrahabr.ru/blog/19305.html

Надеюсь на интересный ответ.
Спасибо за статью! :)
что-то не нашёл я нигде вашего сообщения =)...
Удивительно! :) И здесь http://karellen.habrahabr.ru/blog/19305.html тоже? :)
Странно это все. Похоже, я или забыл его опубликовать, или некие мистические силы не дают вам его прочитать. :) Попробуйте по той же ссылке еще раз, пожалуйста.
Спасибо за статью - я рад, что тема высоких нагрузок и оптимизации все чаще всплывает в рунете. По самой статье пара замечаний:

1. При работе с FastCGI речь идет о процессах, а не о потоках. Каждый процесс занимает довольно много в памяти, поэтому делать их много нежелательно (так же, как нежелательно разрешать слишком много процессов апача). И конечно, сервер надо настраивать так, чтобы при нехватке процессов пользователи просто висели в ожидании, а не получали 500 ошибку.

2. Mysql query cache в большинстве случаев весьма неэффективен. Проблема в том, что у него совершенно тупой механизм инвалидации кэша: при любом изменении в таблице сбрасываются все закэшированные результаты запросов, относящиеся к этой таблице. Если вы пишете cms, то это еще куда ни шло, но в интерактивных веб-приложениях данные меняются часто, поэтому кэш почти не работает. В общем, query cache имеет смысл включать (с помощью хинтов) только для некоторых запросов.

3. Не сказано ни слова про memcached. Для такой актуальной статьи это даже странно ;)

P.S. Если вдруг еще не в курсе - осенью будет HighLoad 2007. Приходите - как участник, а может и как докладчик :)
жалко, не попал, ой как жалко.. Я тем временем вовсе обиделся на php, ушёл в мир модулей apache и чистого Си.. =)) Черт!
О, тема модулей и чистого Си для HighLoad тоже очень актуальна. Приходите на следующую конференцию! :)

Совет - посмотрите в сторону написания модулей для nginx (также на чистом Си) - его архитектура позволяет приложению работать куда эффективнее.

Кстати, в применении к какому проекты Вы занимаетесь оптимизацией, если не секрет?
в следующем году будет? К тому времени возможно будет альфа версия моего проекта для высоконагруженных приложений, авторы которых все равно хотят использовать MVC/EventDriven программирование, но не хотят платить за него дорогой ценой процессорного времени (как сейчас почти во всех фреймворках - django, zendframework (особенно он!), ruby... :) Код можно будет писать на python и возможно даже смешивать его с php. =).
сейчас я создаю инструментарий для своего собственного проекта, нагрузка которого будет в районе 500-1000 req/s. Ни один из вариантов существующих в данных момент мне не подходит. Самый близкий - django+psyco :)
все отлично, только с кешем ничего не понял.
Используйте константы для того что никогда не меняется. Они парсятся в самом начале и лежат вообще в другом куске памяти чем обычные переменные. Конструкции вида $str = 'some' . STR_CONSTANT и выглядят к тому же лучше. Особо грамотно - перенос строки. Обзывают его по-разному, я же люблю NL (NewLine) или CRLF(CarretReturnLineFeed)


К слову, в PHP есть константа PHP_EOL.
Ссылка на ваш скрипт объединения Zend Framework не работает.
надо ж было такую статью забацать 3 года назад мне, до сих пор «спасибо» говорят =) А я сам уже больше 2х лет вообще на PHP не пишу… =)
Не увидел, что некропост =) Почему ушли с PHP, если не секрет?
Python + C.
Настолько потрясён логикой Python, что в сторону PHP даже и не смотрю больше. Особенно чтобы не делать таких извращений как в этой статье )
Понятно, буду иметь ввиду )
Sign up to leave a comment.

Articles