Comments 147
Спасибо, Док. Вы молодец.
> Разбивайте программу и любой _блог_ на инициализацию, настройку...
:)
Хорошая статья. Спасибо.
:)
Хорошая статья. Спасибо.
спасибо =)) а почему lighthtppd ??? а не nginx ???
а если у меня несколько fcgi-backend??? да еще и на удаленных машинах (пресловутые tcp сокеты?? ;) ?
а если у меня несколько fcgi-backend??? да еще и на удаленных машинах (пресловутые tcp сокеты?? ;) ?
почему бы и нет? В lighttpd можно балансировку нагрузки по нескольким fcgi-серверам парой строчек сделать, см. доки.
nginx мне тоже более симпатичен, поэтому держите плюсь, но lighttd ни в чём ему не уступает.
:) Нам nginx очень помог своим ngx_http_memcached_module. Это действительно оказалось очень удобным и быстрым, при условии адекватной генерации линков и ключей. Борьба с персонализацией осуществляется генерацией $memcached_key исходя из ngx_http_userid_module-вского $uid_got.
Большое Вам спасибо!
Весьма интересно было почитать :)
отлично! Очень полезно для того, кто учит PHP по манам. Спасибо.
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 объекты передаются по ссылке.
$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 резволится в объект, с которым уже и выполняются последующие действия (присвоение свойства).
При передаче же по значению, присваивание нового значения локальной переменной никак не затрагивает исходную, вне зависимости от того, какого типа было значение.
Пример с "$x->value = 1" к этому не относится, т.к. здесь $x резволится в объект, с которым уже и выполняются последующие действия (присвоение свойства).
deprecated
надо так
function func(&x) {
x = 1;
}
надо так
function func(&x) {
x = 1;
}
Большое спасибо. Наконец то серьезно написали об оптимизации.
Стандартный механизм сессий бы еще в "...о возможных тратах...", а то уж больно тормозной он
Стандартный механизм сессий бы еще в "...о возможных тратах...", а то уж больно тормозной он
Обработка тонны require_once и include_once
Решение "влоб" нашлось само собой
А решение не в лоб, а в глаз — использовать автоподгрузку (в общем случае __autoload).
не вариант. Время тратится не на парсинг строчки require в файле, а на заглядывание в файловую систему, просмотр mtime файла и тп. Поэкспериментируйте =).
__autoload работает медленее явных require_once, include_once. Проверено опытным путем.
А почему APD, а не xdebug? Есть какие-то нарекания к последнему, или просто, что первое под руку попалось?
не ясно преимущество использования лямбда-функций при обходе массивов, ведь код в 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 добавляет некоторую задержку.
$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 итераций мало что даст.
уже умудрился разогнать ваш пример в почти 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
Про лямбда-функции, каюсь, я не имел ввиду здесь разгон в скорости (создание какой-нибудь простой фунции будет быстрее), но выглядит куда понятнее.
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? :)
Конечно, есть и вопросы, например, почему LigHTTPd, а не nginx?
Opcode Cacher? Xcache? :)
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 вообще страннен, классы надо делать статическими, если нужно, а не если можно.
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 делали.
2. чтобы всё было подконтролем, в независимости от того что решат сделать дефолтным в следующей поставке php ;)
3. PDO_* работает конечно медленнее чем mysql, т.к. он является для него оберткой. С транзакциями в MySQL при постоянных подключениях есть одни огромные грабли - нужно в конце скрипта не забывать транзакции откатывать или коммитить. Потому что сам он этого делать уже не будет (т.к. коннект не рвётся)
5. Я в общем-то и написал "не пытайтесь ничего скоприовать по ссылке пока это действительно не будет необходимым" ;).
6. Просто на моих глазах было много программистов - которым уж очень нужно было всегда создавать экземпляры классов... Даже для factory делали.
3. ага, а любое действие, которое нужно "не забыть" - это уже ошибка, ибо должно делаться автоматом.
и, самое главное, нельзя полагаться на то, что выполнение вообще дойдет до вашего "не забытого" закрытия(commit/rollback т.е.) транзакции, т.к. скрипт может быть убит или самоубиться по разным, часто не зависящим от него причинам, сильно надежнее все же без pconnect жить.
и, самое главное, нельзя полагаться на то, что выполнение вообще дойдет до вашего "не забытого" закрытия(commit/rollback т.е.) транзакции, т.к. скрипт может быть убит или самоубиться по разным, часто не зависящим от него причинам, сильно надежнее все же без pconnect жить.
я потестирую транзакции, возможно модель постоянных соединений в PDO_MYSQL работает несколько по-иному.
Это конечно, полагаться на то, что скрипт "доживёт" до конца в PHP — большая ошибка, не настролько он надёжен. Но проблемы с транзакциями на 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 :-)
Спасибо автору!
Одно добавление из моего личного опыта. У меня нет столько опыта, чтобы быть экспертом во всех областях. Поэтому я использую стандартные настройки сервера и программ, общие правила по написанию кода, не стараюсь добиваться максимальной производительности от функции. Два критерия хорошо кода - понятность и красота :) В результате 80% производительности определяется тем, как спроектирована система. Не бойтесь потратить ваше время на обдумывание и проектирования.
Одно добавление из моего личного опыта. У меня нет столько опыта, чтобы быть экспертом во всех областях. Поэтому я использую стандартные настройки сервера и программ, общие правила по написанию кода, не стараюсь добиваться максимальной производительности от функции. Два критерия хорошо кода - понятность и красота :) В результате 80% производительности определяется тем, как спроектирована система. Не бойтесь потратить ваше время на обдумывание и проектирования.
Категорически против.
Никогда не тратьте время на предварительное проектирование: в определенный момент разработка встает колом по причине "недостаточно проработанной архитектуры системы". Код должен сам говорить, где хорошо, а где плохо. TDD вам в руки. ;-)
Никогда не тратьте время на предварительное проектирование: в определенный момент разработка встает колом по причине "недостаточно проработанной архитектуры системы". Код должен сам говорить, где хорошо, а где плохо. TDD вам в руки. ;-)
TDD и отсутствие проектирования архитектуры не имеют между собой ничего общего. Всегда нужно сначала думать а потом делать, иначе ничего хорошего не выйдет. Практики TDD же позволяют сначала разрабатывать тесты, а уж потом писать для них код.
Не путайте молодёжь =)
Не путайте молодёжь =)
Думать, безусловно, надо. Не надо много думать.
Согласитесь, мало найдется проектов объемом больше трех человеко-месяцев, которые, несмотря на изначальное подробное описание и проектирование "до последней кнопки", не вызывали бы ощущения общирного "костылизма" и мыслей "всю эту хрень переделать". Проектная документация, как правило, устаревает на полпути к дедлайну, после чего на нее (документацию) вообще забивают по причине нехватки времени ;-) Так что подробное проектирование дизайна системы в начале проекта обычно вредит самому проекту, потому что позже команда не может найти в себе силы перекроить дизайн. И чем больше проект - тем хуже результат. Я наблюдал это многократно в разных софтверных компаниях.
Спасти положение может либо рефакторинг, либо переделка "с нуля". А теперь скажите, какой рефакторинг возможен без TDD? Вы лично подпишетесь рефакторить систему с 2МБ пхп-шного кода без наличия тестов на код? ;-) Сила TDD как раз-таки в том, что использование TDD позволяет измененять дизайн системы (читай делать перепроектирование системы) без ущерба качества системы в тот момент, когда разработчик посчитает это нужным. Т.е. фактически не думать о проектировании "на потом". Ключевое слово в TDD рефакторинг.
Согласитесь, мало найдется проектов объемом больше трех человеко-месяцев, которые, несмотря на изначальное подробное описание и проектирование "до последней кнопки", не вызывали бы ощущения общирного "костылизма" и мыслей "всю эту хрень переделать". Проектная документация, как правило, устаревает на полпути к дедлайну, после чего на нее (документацию) вообще забивают по причине нехватки времени ;-) Так что подробное проектирование дизайна системы в начале проекта обычно вредит самому проекту, потому что позже команда не может найти в себе силы перекроить дизайн. И чем больше проект - тем хуже результат. Я наблюдал это многократно в разных софтверных компаниях.
Спасти положение может либо рефакторинг, либо переделка "с нуля". А теперь скажите, какой рефакторинг возможен без TDD? Вы лично подпишетесь рефакторить систему с 2МБ пхп-шного кода без наличия тестов на код? ;-) Сила TDD как раз-таки в том, что использование TDD позволяет измененять дизайн системы (читай делать перепроектирование системы) без ущерба качества системы в тот момент, когда разработчик посчитает это нужным. Т.е. фактически не думать о проектировании "на потом". Ключевое слово в TDD рефакторинг.
я конечно не знаю - может вам заняться нечем вот вы и мусолите одно и тоже по десять раз... я лично был свидетелем проектов 12 девелоперов * 6 месяцев, 80% которых были описаны изначально. И что вы мне доказываете в чем сила TDD - когда я и сам это прекрасно знаю и ни в коем случае не ругаюсь на экстремальное программирование - даже наоборот =).
Была один раз задача - написать торрент-трекер, так если бы мы более 60% времени изначально не потратили на описание внутренней архитектуры и поиск проблем в зародыше - потратили бы уйму человеко-часов (слава богу, не своих) на их нахождение в процессе работы.
Была один раз задача - написать торрент-трекер, так если бы мы более 60% времени изначально не потратили на описание внутренней архитектуры и поиск проблем в зародыше - потратили бы уйму человеко-часов (слава богу, не своих) на их нахождение в процессе работы.
Согласен с mocksoul. TDD и архитектура - разные понятия. Сравнивать нельзя. Касательно проектирования. Если нет четкого представления для чего, что должна делать программа и как этого достичь (я не говорю о расположении кнопочек), то программирование будет как парусник, у которого нет руля и управлять парусом нельзя. Плывем очень быстро, но сменился ветерок, и уже несемся в другую сторону. Мне это надо? Я все-таки получаю деньги за результат, а не за количество строчек и сколько раз я их переписывал. :)
В школе есть такое понятие как черновик и чистовик. Не знаю как сейчас, но раньше мы писали в черновик, что-то там правили, потом в чистовик. Ребенок пишет в черновик и знает, что можно делать не аккуратно и не сильно старается. Позже можно будет и исправить. Это же не чистовик. Не реальная жизнь – это чистовик. И делать надо сразу хорошо, исправить не всегда удается. Может быть поэтому, как вы пишите “Проектная документация, как правило, устаревает на полпути к дедлайну, после чего на нее (документацию) вообще забивают по причине нехватки времени”?
В школе есть такое понятие как черновик и чистовик. Не знаю как сейчас, но раньше мы писали в черновик, что-то там правили, потом в чистовик. Ребенок пишет в черновик и знает, что можно делать не аккуратно и не сильно старается. Позже можно будет и исправить. Это же не чистовик. Не реальная жизнь – это чистовик. И делать надо сразу хорошо, исправить не всегда удается. Может быть поэтому, как вы пишите “Проектная документация, как правило, устаревает на полпути к дедлайну, после чего на нее (документацию) вообще забивают по причине нехватки времени”?
Дебилизм, столь часто употребляемый в статье, пишется через "е" ;)
Понторезный стиль изложения. Неприятно читать такие статьи.
Зато полно конкретики, а это как раз то, что ценно в данном случае. В отличие от обтекаемых рассуждений ведущего программиста Рамблера о highload-архитектуре на конференции, когда он толком ни на один вопрос не ответил.
насчет is_null - почти все подобные функции работают медленне
например empty работает на 10-15% медленне, чем просто if ($var).
например empty работает на 10-15% медленне, чем просто if ($var).
Вообще статья хорошая, особенно фраза "Увеличение быстродействия на 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 раз. И читаемость повыше для несложных манипуляций.
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-ем. Сортировку, например.
Ахринительно полезная статья. Искренне благодарен.
Автор молодец, что потрудился и написал много полезных вещей для php-программистов (начинающих и не очень), но позволю себе заметить, что со знанием принципа работы lighttpd+php+fascgi у него пробел.
PHP никогда не запускает много потоков в одном процессе, не умеет он этого (а если вдруг я не прав, и он умеет, то буду счастлив узнать - как этого добиться). min-procs и max-procs действительно нужно ставить в 1, но не потому, что sharedmem не будет иметь смысла, а потому что балансировщик нагрузки у лайти корявый. А так он запускает один головной php-процесс в специальном режиме, а тот плодит заданное количество процессов и занимается распределением запросов между ними. А sharedmem имеет смысл как раз при работе с несколькими процессами, для этого его и придумали. А вообще, php лучше запускать независимо от лайти под другим пользователем.
То, что у автора выделено красным цветом - антисовет! Не запускайте такое огромное количество php-процессов - это верный путь к DoS'у. 20-30 процессов - это предел (зависит ещё от железа). Если все они заняты, то скорее всего камень загружен под самое не балуйся, так что лучше пусть лайти 500 плюнет, а не нагнетает обстановку, ибо тогда даже админ в консоли не войдёт.
Автору рекомендую исправить.
PHP никогда не запускает много потоков в одном процессе, не умеет он этого (а если вдруг я не прав, и он умеет, то буду счастлив узнать - как этого добиться). min-procs и max-procs действительно нужно ставить в 1, но не потому, что sharedmem не будет иметь смысла, а потому что балансировщик нагрузки у лайти корявый. А так он запускает один головной php-процесс в специальном режиме, а тот плодит заданное количество процессов и занимается распределением запросов между ними. А sharedmem имеет смысл как раз при работе с несколькими процессами, для этого его и придумали. А вообще, php лучше запускать независимо от лайти под другим пользователем.
То, что у автора выделено красным цветом - антисовет! Не запускайте такое огромное количество php-процессов - это верный путь к DoS'у. 20-30 процессов - это предел (зависит ещё от железа). Если все они заняты, то скорее всего камень загружен под самое не балуйся, так что лучше пусть лайти 500 плюнет, а не нагнетает обстановку, ибо тогда даже админ в консоли не войдёт.
Автору рекомендую исправить.
эээ.. потоки php как раз умеет. И красным цветом я говорил про потоки но уж никак не про процессы. И балансировать нагрузку надо не такими вещами, а чем-то более гибким ;)
О том как добится чтобы пхп запускал потоки - см. bin-environment в предоставленном мной конфиге. И 128 потоков PHP - я забыл упомянуть - это для 8-ядерного сервера хорошо... =) Другими словами прочитав статью головой-то все равно думать надо. Это не HowTo.
О том как добится чтобы пхп запускал потоки - см. bin-environment в предоставленном мной конфиге. И 128 потоков PHP - я забыл упомянуть - это для 8-ядерного сервера хорошо... =) Другими словами прочитав статью головой-то все равно думать надо. Это не HowTo.
для линукса 2 понятия такие как поток и процесс являются тождественными. или я ошибаюсь?
Статья может ввести в заблуждение.
По поводу: LigHTTPd, ну кому что, но зачем его-то?
1-й пункт: нужно применять там где нужно обычные вызовы, там где нужно _once. При чем тут оптимизация?
2-й пункт: практически никогда array_walk не будет быстрее языковых конструкций. Да и читаемость ужасная.
3-й пункт: Передавайте по ссылке то, что нужно передать по ссылке. При чем тут оптимизация.
4-й пункт: Вредный совет. Статические классы спецефичны и заменить обычные классы полностью или даже частично не могут. Применяются там, где нужно.
5-й пункт: На счет комментариев... При чем тут оптимизация. Комментарии просто нужны и лучше напишите их больше, чем меньше.
6-й пункт: Рекурсии... Что так тормозят? Иногда архиполезно...
С 9-м пунктом согласен кроме sprintf. Хотя иногда удобно ее использовать.
12-й да.
На счет кеширования обсуждалось.
Статья спорная и может ввести в заблуждение новичков.
По поводу: LigHTTPd, ну кому что, но зачем его-то?
1-й пункт: нужно применять там где нужно обычные вызовы, там где нужно _once. При чем тут оптимизация?
2-й пункт: практически никогда array_walk не будет быстрее языковых конструкций. Да и читаемость ужасная.
3-й пункт: Передавайте по ссылке то, что нужно передать по ссылке. При чем тут оптимизация.
4-й пункт: Вредный совет. Статические классы спецефичны и заменить обычные классы полностью или даже частично не могут. Применяются там, где нужно.
5-й пункт: На счет комментариев... При чем тут оптимизация. Комментарии просто нужны и лучше напишите их больше, чем меньше.
6-й пункт: Рекурсии... Что так тормозят? Иногда архиполезно...
С 9-м пунктом согласен кроме sprintf. Хотя иногда удобно ее использовать.
12-й да.
На счет кеширования обсуждалось.
Статья спорная и может ввести в заблуждение новичков.
кто-то находит полезным, кто-то вредным. Мнение субъективно по своей сути =).
Многое я писал для того чтобы наоборот не пытались оптимизировать там, где ничего не получится (передача по ссылкам). Заменять обычные объекты статичными (или по крайней мере сильно стараться это делать) - глупо. Я писал о том, что просто забывать о статических классах не стоит. По поводу комментариев - опять же слышал несколько мнений в виде "файлы должны быть маааленькими и комментарии тормозят парсинг" (абсурд, но не все это понимают). Рекурсии полезны, но если можно обойтись без них - лучше без них. Тем более учитывая что рекурсия без проверки вложенности может когда-нибудь вызвать segfault при перегрузке стека php. Sprintf в строках я дал опять-таки для примера, чтобы просто не забывали о его существовании ;).
Поймите - это не howto, это просто мысли в слух. Для каждого конкретного случая можно вспомнить что то из этой статьи а потом подумать "стоит это тут использовать или нет". Делать бездумно - глупо впринципе.
Многое я писал для того чтобы наоборот не пытались оптимизировать там, где ничего не получится (передача по ссылкам). Заменять обычные объекты статичными (или по крайней мере сильно стараться это делать) - глупо. Я писал о том, что просто забывать о статических классах не стоит. По поводу комментариев - опять же слышал несколько мнений в виде "файлы должны быть маааленькими и комментарии тормозят парсинг" (абсурд, но не все это понимают). Рекурсии полезны, но если можно обойтись без них - лучше без них. Тем более учитывая что рекурсия без проверки вложенности может когда-нибудь вызвать segfault при перегрузке стека php. Sprintf в строках я дал опять-таки для примера, чтобы просто не забывали о его существовании ;).
Поймите - это не howto, это просто мысли в слух. Для каждого конкретного случая можно вспомнить что то из этой статьи а потом подумать "стоит это тут использовать или нет". Делать бездумно - глупо впринципе.
чтобы отключить все ненужные модули при сборке php, достаточно
и дальше указать необходимые --enable и --with
--disable-all --without-all --disable-reflection
и дальше указать необходимые --enable и --with
Огромное спасибо! Как говорят, "Чтобы стать профессионалом, всегда нужен учитель".
Жду продолжения/развития, так как с кэшем как раз мало практики.
Жду продолжения/развития, так как с кэшем как раз мало практики.
Вы бы рекомендации APC убрали — самый тормозной кеш, даром что в PECL входит, а более быстрые конкуренты точно так же работают с shared memory (кроме ZO).
а Вы что используете?
"сильно тормозной" это всё-таки слишком сильно сказано за xcache
за xcache http://www.dailymotion.com/blog/video/37… - далеко не всегда он аутсайдер. Да и вообще разброс по скорости там не настолько критичен =).
Разве что xcache надо пробовать. Это да.
за xcache http://www.dailymotion.com/blog/video/37… - далеко не всегда он аутсайдер. Да и вообще разброс по скорости там не настолько критичен =).
Разве что xcache надо пробовать. Это да.
упс линк кривой нарисовал - http://startrekguide.com/scripts/benchma… - вот.
Всё возможно. Я APC пробовал несколько раз, всегда снимал из-за глюков при включении оптимизации (в основном, у нас нагруженные, сложные проекты, поэтому глюки проявляются быстро), видел несколько benchmarks, результаты везде не в пользу APC, в первый раз вижу, чтобы APC настолько близок к лидерам был.
ну у них в доках сказано "ни за что не включайте оптимизацию - глючит!" =)) Сам пару часов затылок чесал при виде разваливающегося проекта ;). Но без оптимизации - как часы.
eAccelerator мне совсем не нра из-за непрозрачной архитектуры (лениво в исходниках копаться и рассматривать что же они там творят и API глядеть для PHP).. а вот xcache - растёт. Последний раз когда глядел на него - он в альфе был. Сейчас вроде как 1.2 уже. Надо ставить и пробовать. Да =).
eAccelerator мне совсем не нра из-за непрозрачной архитектуры (лениво в исходниках копаться и рассматривать что же они там творят и API глядеть для PHP).. а вот xcache - растёт. Последний раз когда глядел на него - он в альфе был. Сейчас вроде как 1.2 уже. Надо ставить и пробовать. Да =).
Отличная статья.
Два года уже об оптимизации ни чего не слышно было.
Два года уже об оптимизации ни чего не слышно было.
Огромнейшее спасибо! Прекрасная статья, однако для новичка сложновато будет...
Дал своим прогерам прочитать. Им понравилось.
А вы где работаете?
А вы где работаете?
> unix-сокеты много шустрее чем tcp-сокеты.
unix-сокеты *чуть-чуть* быстрее tcp.
> Opcode Cacher. Или кешер байткода. Или "что за дибилизм - парсить одни и те же файлы при каждом запросе?!". Очень (ОЧЕНЬ!) рекомендую APC (Alternative PHP Cache) который лежит в PECL. Можно так же eAccelerator или даже ZendOptimizer.
Вопиющая безграмотность - ZendOptimizer это не "кэшер байткода".
unix-сокеты *чуть-чуть* быстрее tcp.
> Opcode Cacher. Или кешер байткода. Или "что за дибилизм - парсить одни и те же файлы при каждом запросе?!". Очень (ОЧЕНЬ!) рекомендую APC (Alternative PHP Cache) который лежит в PECL. Можно так же eAccelerator или даже ZendOptimizer.
Вопиющая безграмотность - ZendOptimizer это не "кэшер байткода".
ZendOptimizer обладает этой функциональностью. Так? Лишь бы ляпнуть, честное слово.
unix-сокеты... а вы потестите, потестите... скорость установки соединения, нагрузка на ядро при большом кол-ве соединений, использование буфера (не перемешивающегося с буфером tcp)... вот и будет вам "чуть чуть" ;)
unix-сокеты... а вы потестите, потестите... скорость установки соединения, нагрузка на ядро при большом кол-ве соединений, использование буфера (не перемешивающегося с буфером tcp)... вот и будет вам "чуть чуть" ;)
ZendOptimizer НЕ обладает этой функциональностью. Прежде чем писать статьи, ознакомьтесь с материалом, о котором пишете.
AF_UNIX сокеты на Linux, про который вы пишете незначительно быстрее чем AF_INET, даже на больших нагрузках. Это касается и скорости установки соединений (роутинг локальных tcp соединения в линуксе происходят через отдельную таблицу local) и скорости работы. Почему Вы считаете что ядро писали идиоты ? Вы сами тестировали ?
AF_UNIX сокеты на Linux, про который вы пишете незначительно быстрее чем AF_INET, даже на больших нагрузках. Это касается и скорости установки соединений (роутинг локальных tcp соединения в линуксе происходят через отдельную таблицу local) и скорости работы. Почему Вы считаете что ядро писали идиоты ? Вы сами тестировали ?
вы ошиблись и воинственно реагируете - а это не красит ;) ошиблись просто перепутав - опкод кеширует не оптимайзер, а zend platform (ранее zend accelerator)
в том то и дело - что я ошибся не в указании банковского счета (что действительно испортило бы мне настроение) - а всего на всего в названиях программ - и к таким замечаниям вроде "ох! это вопиющая безграмотность!" отношусь с должным сарказмом =). Zend Platform, так Zend Platform, каюсь, перепутал, подправлю статью.
Я извиняюсь, что так через стока времени тут возникаю, но — статья не подправлена, кажись, ни по одному из пунктов, по которым Ваше обещание подправить проскользнуло в комментах. Вы окончательно на это забили? И не появилось ли у Вас новых соображений? Тема-то всё ещё весьма актуальна, и на статью ссылаются. (За неё большой респект Вам!)
вау =)
за прошедшие два года многое изменилось… я больше не пишу вообще, целиком ушёл в мир Python/C/D. Увы, сейчас все мои эти танцы с бубном вокруг PHP кажутся детским садом — если в идеологию программного языка или платформы не вложена скорость/удобство — лучше и не пытаться это привить на верхних слоях.
И содержание блока «Зачем это всё?» уже совсем не отражает моё состояние =). Проекты надо делать такими, которые могут выдержать даже если вдруг завтра придёт в 1000 раз больше пользователей чем сегодня. И если об этом задумываться в самом низу (о чём, увы, в PHP думали не много) — то это перестаёт быть такой уж сложной проблемой. Всего-то надо не обогревать атмосферу тонной никому не нужных конструкций =).
Тем не менее мнение о PHP осталось сдержанно-холодное, но не гневное. Я правда не могу придумать себе сейчас такую задачку, в которой мой выбор пал бы снова на него, но зато глядя на него можно увидеть действительно потрясающий питон =)))))) Не было бы сравнения — не получилось бы))
за прошедшие два года многое изменилось… я больше не пишу вообще, целиком ушёл в мир Python/C/D. Увы, сейчас все мои эти танцы с бубном вокруг PHP кажутся детским садом — если в идеологию программного языка или платформы не вложена скорость/удобство — лучше и не пытаться это привить на верхних слоях.
И содержание блока «Зачем это всё?» уже совсем не отражает моё состояние =). Проекты надо делать такими, которые могут выдержать даже если вдруг завтра придёт в 1000 раз больше пользователей чем сегодня. И если об этом задумываться в самом низу (о чём, увы, в PHP думали не много) — то это перестаёт быть такой уж сложной проблемой. Всего-то надо не обогревать атмосферу тонной никому не нужных конструкций =).
Тем не менее мнение о PHP осталось сдержанно-холодное, но не гневное. Я правда не могу придумать себе сейчас такую задачку, в которой мой выбор пал бы снова на него, но зато глядя на него можно увидеть действительно потрясающий питон =)))))) Не было бы сравнения — не получилось бы))
UFO just landed and posted this here
Работа полезная, спасибо.
В таком решении на ряду - слитно?
и закрывающая скобка в примере с array_walk
В таком решении на ряду - слитно?
и закрывающая скобка в примере с array_walk
Здравствуйте,
Все, что хотел, написал вам письмом, но думаю, что и сообществу может оказаться интересно и полезно, а я для себя найду какие-то свои ошибки и восполню пробелы в знаниях, которые наверняка имеются.
Странно, что Хабрахабр не пускает мое сообщение как комментарий. Видимо, оно слишком длинное - получилось 18 пунктов. :) Так что простите меня за саморекламу, но, видимо, придется писать в свой блог и давать ссылку. :)
http://karellen.habrahabr.ru/blog/19305.html
Надеюсь на интересный ответ.
Спасибо за статью! :)
Все, что хотел, написал вам письмом, но думаю, что и сообществу может оказаться интересно и полезно, а я для себя найду какие-то свои ошибки и восполню пробелы в знаниях, которые наверняка имеются.
Странно, что Хабрахабр не пускает мое сообщение как комментарий. Видимо, оно слишком длинное - получилось 18 пунктов. :) Так что простите меня за саморекламу, но, видимо, придется писать в свой блог и давать ссылку. :)
http://karellen.habrahabr.ru/blog/19305.html
Надеюсь на интересный ответ.
Спасибо за статью! :)
Спасибо за статью - я рад, что тема высоких нагрузок и оптимизации все чаще всплывает в рунете. По самой статье пара замечаний:
1. При работе с FastCGI речь идет о процессах, а не о потоках. Каждый процесс занимает довольно много в памяти, поэтому делать их много нежелательно (так же, как нежелательно разрешать слишком много процессов апача). И конечно, сервер надо настраивать так, чтобы при нехватке процессов пользователи просто висели в ожидании, а не получали 500 ошибку.
2. Mysql query cache в большинстве случаев весьма неэффективен. Проблема в том, что у него совершенно тупой механизм инвалидации кэша: при любом изменении в таблице сбрасываются все закэшированные результаты запросов, относящиеся к этой таблице. Если вы пишете cms, то это еще куда ни шло, но в интерактивных веб-приложениях данные меняются часто, поэтому кэш почти не работает. В общем, query cache имеет смысл включать (с помощью хинтов) только для некоторых запросов.
3. Не сказано ни слова про memcached. Для такой актуальной статьи это даже странно ;)
P.S. Если вдруг еще не в курсе - осенью будет HighLoad 2007. Приходите - как участник, а может и как докладчик :)
1. При работе с FastCGI речь идет о процессах, а не о потоках. Каждый процесс занимает довольно много в памяти, поэтому делать их много нежелательно (так же, как нежелательно разрешать слишком много процессов апача). И конечно, сервер надо настраивать так, чтобы при нехватке процессов пользователи просто висели в ожидании, а не получали 500 ошибку.
2. Mysql query cache в большинстве случаев весьма неэффективен. Проблема в том, что у него совершенно тупой механизм инвалидации кэша: при любом изменении в таблице сбрасываются все закэшированные результаты запросов, относящиеся к этой таблице. Если вы пишете cms, то это еще куда ни шло, но в интерактивных веб-приложениях данные меняются часто, поэтому кэш почти не работает. В общем, query cache имеет смысл включать (с помощью хинтов) только для некоторых запросов.
3. Не сказано ни слова про memcached. Для такой актуальной статьи это даже странно ;)
P.S. Если вдруг еще не в курсе - осенью будет HighLoad 2007. Приходите - как участник, а может и как докладчик :)
жалко, не попал, ой как жалко.. Я тем временем вовсе обиделся на php, ушёл в мир модулей apache и чистого Си.. =)) Черт!
О, тема модулей и чистого Си для HighLoad тоже очень актуальна. Приходите на следующую конференцию! :)
Совет - посмотрите в сторону написания модулей для nginx (также на чистом Си) - его архитектура позволяет приложению работать куда эффективнее.
Кстати, в применении к какому проекты Вы занимаетесь оптимизацией, если не секрет?
Совет - посмотрите в сторону написания модулей для 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 не работает.
спасибо!
Sign up to leave a comment.
Кропотливая оптимизация PHP-приложений (рассматриваю PHP5, но большинство справедливо и для 4-й ветки)