Кропотливая оптимизация PHP-приложений (рассматриваю PHP5, но большинство справедливо и для 4-й ветки)

    Когда во сне снится «ой а если сервера не хватит...»


    Для начала, Доброй Ночи. Пишу что-то полезное вроде впервые (если не считать разного рода полу-тестов в моём блоге). Человек я допытливый до жути, неожиданно в голову пришло, что могу помочь сэкономить кому-то много времени ;).




    В общем когда на PHP создаются достаточно большие проекты (>100000 строк кода) желание сделать «правильно» то, что было сделано давно грозит повергнуть всё в хаос. По крайней мере для новых программистов, которые могут прийти в компанию через неделю, месяц, год… Решение — четкая систематизация с самого начала и установление жестких архитектурных правил. Для себя я решил — не используя фреймворки писать буду только «Hello World»-сайты. Не мудрствуя лукаво когда подумал о фреймворках полистал, почитал, но решил отдаться-таки зенду с его ZendFramework. Добротный он, хотя и изменений я в нём для себя сделал огромное количество.


    В таком решении на ряду со всеми возможными плюсами и удобством неожиданно встаёт вопрос-стена: теперь у меня бизнес логика занимает, наверное, где-то вовсе 1-2% от времени исполнения всей программы. Плата за удобство и ООП (или «удобство ООП»? Наверное даже просто «удобство» или просто «ООП» — это почти одно и то же ;)) — огромное количество сопутствующего и управляющего кода.


    В общем когда я делал новый проект — была цель — не менее 50 запросов в секунду на захудалом Celeron 2.6GHz. Т.е. около 0.02сек на запрос, включая mysql и так далее тому подобное. За время создания проекта я его умудрялся разгонять в несколько раз какими-то улучшениями. Какими? Налейте чашечку кофе — и добро пожаловать в мир мудрого девелопинга :) Сразу скажу — получилось.


    Оптимизация от А до Я. Рецепт супчика от MockSoul :)



    Этап 0. Готовимся



    Окружение? Моя наилюбимейшая схема:


    1. LigHTTPd. Под линуксом. Со включенным sys-epoll;

    2. PHP5. Через FastCGI. PHP должен быть собран с поддержкой CGI, sharedmem (или threads, лучше sharedmem — а и то и другое сразу не скомпилится ;)). Дикий пример с чем я собираю пхп:


      ./configure' '--prefix=/usr/lib/php5' '--host=i686-pc-linux-gnu' '--mandir=/usr/lib/php5/man' '--infodir=/usr/lib/php5/info' '--sysconfdir=/etc' '--cache-file=./config.cache' '--disable-cli' '--enable-cgi' '--enable-fastcgi' '--disable-discard-path' '--disable-force-cgi-redirect' '--with-config-file-path=/etc/php/cgi-php5' '--with-config-file-scan-dir=/etc/php/cgi-php5/ext-active' '--without-pear' '--disable-bcmath' '--with-bz2' '--disable-calendar' '--disable-ctype' '--without-curl' '--without-curlwrappers' '--disable-dbase' '--disable-exif' '--without-fbsql' '--without-fdftk' '--disable-filter' '--disable-ftp' '--with-gettext' '--without-gmp' '--disable-hash' '--disable-ipv6' '--disable-json' '--without-kerberos' '--enable-mbstring' '--with-mcrypt' '--without-mhash' '--without-msql' '--without-mssql' '--with-ncurses' '--with-openssl' '--with-openssl-dir=/usr' '--disable-pcntl' '--without-pgsql' '--without-pspell' '--without-recode' '--disable-simplexml' '--enable-shmop' '--with-snmp' '--disable-soap' '--enable-sockets' '--without-sybase' '--without-sybase-ct' '--disable-sysvmsg' '--disable-sysvsem' '--disable-sysvshm' '--with-tidy' '--disable-tokenizer' '--disable-wddx' '--disable-xmlreader' '--disable-xmlwriter' '--without-xmlrpc' '--without-xsl' '--disable-zip' '--with-zlib' '--disable-debug' '--enable-dba' '--without-cdb' '--without-db4' '--without-flatfile' '--with-gdbm' '--without-inifile' '--without-qdbm' '--with-freetype-dir=/usr' '--with-t1lib=/usr' '--disable-gd-jis-conv' '--with-jpeg-dir=/usr' '--with-png-dir=/usr' '--without-xpm-dir' '--with-gd' '--with-ldap' '--without-ldap-sasl' '--with-mysql=/usr' '--with-mysql-sock=/var/run/mysqld/mysqld.sock' '--without-mysqli' '--without-pdo-dblib' '--with-pdo-mysql=/usr' '--without-pdo-odbc' '--without-pdo-pgsql' '--without-pdo-sqlite' '--with-readline' '--without-libedit' '--with-mm' '--without-sqlite'


      Грамотно прикручиваем к lighttpd, а не абы как:


      fastcgi.server = (
          ".php" => (
              "localhost" => (
                  <b>"socket"          => "/tmp/php5-gmru-sandbox-mocksoul-lighttpd.sock" [#1]</b>,
                  <b>"bin-path"        => "/usr/lib/php5/bin/php-cgi -c " + "/path/to/application/config/php_config_dir" [#2]</b>,
                  <b>"min-procs"       => 1 [#3]</b>,
                  <b>"max-procs"       => 1 [#3]</b>,
                  "bin-environment" => (
                      <b>"PHP_FCGI_CHILDREN" => "32" [#4]</b>,
                      <b>"PHP_FCGI_MAX_REQUESTS" => "3200" [#5]</b>
                  )
              )
          )
      )



      ([#1], [#2],… — так буду ссылаться на комментарии к коду. Если хотите взять код — такие пометки надо будет стереть. Ниже в коде буду придерживаться такой же схемы)


      • [#1] — unix-сокеты много шустрее чем tcp-сокеты. Так что используйте их только если в TCP нет серьёзной необходимости (или, хаха, под Windows :))
      • [#2] — тут я просто показал пример как можно конфиг пхп прикручивать к разному хосту (через -c указываем на папку с php.ini)
      • [#3] — min-procs и max-procs ДОЛЖНЫ БЫТЬ = 1!!! Почему? Потому что далее я скажу про кеширование байткода. Кеш будет нелогичен при кол-ве процессов пхп более 1
      • [#4] — магический танец. Просим php запустить 32 потока в одном процессе для обработки запросов от lighttpd. Важно: если поставить, например, 10 и все 10 будут заняты каким-то диким 10-секундно-выполняющимся-скриптом — lighttpd будет отдавать 500 ошибку! Т.е. количество потоков не увеличивается в реалтайме — ставьте 32, 64 или, даже, 128 (работает это как threadpool)
      • [#5] — просим убить поток и создать новый через энное количество запросов. На всякий случай, ведь php не идеален :).

    3. Opcode Cacher. Или кешер байткода. Или «что за дибилизм — парсить одни и те же файлы при каждом запросе?!». Очень (ОЧЕНЬ!) рекомендую APC (Alternative PHP Cache) который лежит в PECL. Можно так же eAccelerator или даже ZendOptimizer. Вкусы разные бывают… Но при выборе между eAccelerator и APC — я рекомендую APC. Почему? Да хотя бы за возможность положить что угодно в shmem сегмент :). Ниже расскажу.



    Этап 1. Пишем



    Сначала пишем. Пишем и крутим в голове мысли о том как что-то сделать более разумным и быстрым сразу. Чтобы потом не отвлекаться (вообще это наверное совершенно естественное желание любого уважающего себя программиста %))


    Моменты на которые сразу нужно обращать внимание:


    1. Вам, наверное, почти не нужно будет использовать require и include. В основном — require_once и include_once.
    2. Для итерации по массивам, их изменению и фильтрации — учимся использовать array_* функции в пхп. Особенно лямбда-функции:
      <?php
              
      $arr = array('that', 'is', 'this');
      array_walk($arr, create_function('&$v,$k', '$v = $v . " yeah";');
      print_r($arr);
      
      // outputs:
      // Array
      // (
      //   [0] => that yeah
      //   [1] => is yeah
      //   [2] => this yeah
      // )
      
      // А вы бы сделали это циклом? Ай-ай-ай...
      
      ?>

    3. Передача переменной по ссылке (например $a=1; call_func(&$a)) — не влияет на быстродействие. Передача массивов по ссылке — влияет чуть-чуть. Передача классов — влияет очень. Я это к тому — что не передавайте ничего по ссылке надеясь ускорить программу. Передавайте по ссылкам только когда вам это _действительно_ нужно
    4. Делайте классы статическими если можно. Т.е. если для работы класса закрытая инстанция в общем-то и не нужна.
    5. Комментировать можно сколько хочется — кешер байткода все равно комментарии игнорирует. На быстродействие это влияет… хм… на 0.000001% :)
    6. Избегайте глубоких рекурсий. Стандартную задачу — взять список файлов включая поддирректории можно сделать и без рекурсии вовсе =)
    7. Прочитайте грамотные доки. Документацию того же ZendFramework — там много чего полезного даже тем кто фреймворк не использует и использовать не собирается
    8. Старайтесь делить код на логические блоки. Так, чтобы можно было взять 10-20 строчек подряд и сказать — вот тут я делаю ТОЛЬКО ЭТО. Взять другие 10-20 — и сказать а тут я делаю ТОЛЬКО ДРУГОЕ. Кол-во строчек которые надо брать, конечно, зависит от вас. Но лучше чтобы блоки были не более чем по 30-40 строк. Разбивайте программу и любой блог на инициализацию, настройку, работу, сохранение результата (в переменную скажем). При чём тут скорость? Через полгода поймёте ;).
    9. О том «Может сделать мне $a = „some $v inline“ или $a = „some“. $v. „var“ даже думать не стоит. Лично я (имхо) нахожу абсолютно дибильным вставку переменных прямо в строки. Лучшая читаемость:
      • $var = 'some'. $in. 'li'. $ne. ' variable';
      • $var = sprintf('some %sli%s variable', $in, $li);

    10. Используйте константы для того что никогда не меняется. Они парсятся в самом начале и лежат вообще в другом куске памяти чем обычные переменные. Конструкции вида $str = 'some'. STR_CONSTANT и выглядят к тому же лучше. Особо грамотно — перенос строки. Обзывают его по-разному, я же люблю NL (NewLine) или CRLF(CarretReturnLineFeed)
    11. Не забывайте что foreach может и не делать копию массива :)
      foreach ($arr as $key => <b>&$val</b>) { ... }

    12. Как это ни парадоксально но вот такой момент меня в пхп совсем убивает: is_null() — придумана идиотом. if (null === $var) или if ($var === null) быстрее чем if (is_null($var))… дибилизм. Не используйте is_null() :)
    13. Регулярные выражения, работу со строками с помощью str_* функций и прочее оставляю на вашей совести как выходящее за рамки этой и без того раздутой статьи :)

    Этап 2. Размышляем о возможных тратах времени



    Так… вот написали вы чего-нибудь. А теперь давайте посмотрим что обычно отнимает достаточно дофига времени без вашей бизнес-логики:

    1. Коннект к БД
    2. Обработка тонны require_once и include_once
    3. Сами запросы к БД
    4. Где-то храним конфиг и парсим его каждый раз? Используем модели БД и инициализируем их каждый раз? Вообще посмотрите как много одинакового мы делаем каждый запрос!!
    5. Что-то делаем с файловой системой? А зачем? Лично я думаю что можно чуть ли не любой проект написать с вообще отсутствующим IO (конечно, кроме того что будет использовать БД и тп). Не нужно ничего хранить в файловой системе. Мелкое. Большое (какой-нибудь гиговый проиндексированный файл) — нужно


    Это я все отсортировал по важности. А теперь по порядку по каждому ненасытному моменту:

    Коннект к БД


    Всё просто — если владеете сервером — используйте постоянные подключения! PDO_MYSQL, MYSQL — все это умеют )

    Обработка тонны require_once и include_once


    Вот тут начинается веселье =). Для начала я взял посмотрел сколько файлов у меня включаются при ЛЮБОМ запросе в ZendFramework. Оказалось — чуть менее 300 (!!!!). Если не использовать байткод кешер — это будет вообще ненормально долгая процедура.

    Решение „влоб“ нашлось само собой — запихать всё это в один файл. Встал вопрос — а как узнать что у нас всегда инклудится — а что иногда? Вообще размышлять в тот момент особо времени не было поэтому и этот аспект я решил „влоб“ )

    Дикий результат — http://www.mocksoul.ru/pub/dev/mkzend.phps

    Там:
    • Насколько часто обращение к файлу — смотрим через APC кеш по статистике
    • Рисуем табличку
    • Изменяем зенд автоматом :). Типа вырезаем все require_once, комментарии, открывающие и закрывающие пхп теги, лишние пробелы… издеваемся короче :) Смотрите исходник
    • Сохраняем получившеся гигантский скрипт в файлик… )


    Скрипт абсолютно нестабилен и заточен под один проект. Запускать надо через браузер, чтобы APC отработал. Просто как пример. У вас работать не будет со 100% вероятностью =).

    Как оказалось — 300 файлов парсились 2 сек, из байткешера вытаскивались за 0.3 сек, а сгенерированый суперфайл большой парсится 0.7сек а из кеша вытягивается за 0.003сек. Проект сразу разогнался почти в 3 раза :). Маньячная оптимизация, однако. Метод подходит для production-сервера, т.к. девелопить библиотеки которые из другого файла грузятся — невозможно.

    Запросы к БД


    Пройдите экскурс в ДБА и начните, наконец, использовать MYSQL_QUERY_CACHE. В my.cnf пишем query_cache_size = 100M. За кешем следим путём show status like 'qcache%'. Ещё очень плотно читаем доки MySQL относительно Query Cache


    Хватит делать одно и тоже — кешируйте!



    Прочитали конфиг? Распарсили? Получили готовенький массив? Ну и зачем парсить его снова? ) У вас же есть — shared memory под рукой в виде APC! :) Невероятно быстрая скорость работы… Храните в нём все что только можно — конфигурацию, собранные объекты, результаты запросов а-ля „describe table“ (это прерогатива Zend_Db_Table_*). Из кеша данные берутся с невообразимой скоростью — 0.000001с где-то. В памяти, если не дублировать ничего, можно сохранить просто дофига данных. Помните, что 1 гиг — это огромная куча возможной информации. Не используйте IO в файловую систему для этого — лучше память. В зависимости от вашей квалификации — от 10 до 100% прироста скорости. Смотрите ниже про APD ;)

    Зачем вам ФС?



    Используйте ФС как хранитель чего угодно, только если это не влазит в память. Даже если пишите лог или статистику запросов — ложите в APC! И сохраняйте, скажем, каждые 5 минут на винт.

    Этап 3. Устали размышлять о тратах времени. Хотим график перед глазами!



    Это для меня оказалось весьма ценным открытием. В общем пошаговый гид:

    1. Нам нужен PECL APD (Advanced PHP Debugger)
    2. Конфигурим dumpdir для apd в конфиге. Что-то вроде:
      zend_extension=/usr/lib/php5/lib/php/extensions/no-debug-non-zts-20060613/apd.so
      apd.dumpdir="/tmp/php-apd-dump"
    3. В самом главном файлике пишем в сааамом верху apd_set_pprof_trace();, тем самым включая дамп профилера
    4. Делаем 1-100 запросов на сервер. Каждый раз будет сохранятся новый файлик в нашей /tmp/php-apd-dump
    5. Теперь мы можем смотреть результаты профилера либо прямо в консоли — вместе с apd идёт скриптик pprofp
    6. А ещё можем сделать супервещь — преобразовать в более унифицированный формат :). С APD кроме pprofp есть ещё pprof2calltree. Она преобразует дампы профилера в формат, понимаемый cachegrind и KCacheGrind в частности. Полученный файлик открываем в kcachegrind — и рукоплещем от удовольствия.


    В целом — обычный такой профилер получается. Вот только для PHP я раньше такого не делал ;)

    Этап 4. Проверяем



    Проверять скорость простыми запросами на 1 урл при помощи ab или ab2 — глупо.

    Более логичный вариант — сделать список всех (или не всех ;)) урлов, положить в текстовый файлик, взять Siege и тестить. Во время теста следить за TPS (TransactionsPerSecond) на винты (например при помощи iostat из пакета sysstat), следить за загрузкой процессоров, смотреть чтобы в конце не было ответов сервера отличных от 2хх.

    Зачем это всё


    Так сильно пытаться все ускорить нужно когда проект разрастается. Увеличение быстродействия на 10% на 1 сервере даёт прирост в скорости равный 10%. А если у вас уже 10 серверов — то 10%-ое увеличение быстродействие будет равно добавлению ещё одного 11-го сервера. Т.е. +100% в пересчете на 1 сервер. Это много. Это деньги. И это более высокий порог входа для конкурентов ;).

    Ээээ


    2 дня назад сломал ключицу. И писал всё это одной рукой. Памятник мне!!! :))

    Kind Regards, Vadim Burmakin aka MockSoul © 2007
    Поделиться публикацией
    Комментарии 147
      +4
      Спасибо, Док. Вы молодец.
        +1
        > Разбивайте программу и любой _блог_ на инициализацию, настройку...
        :)

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

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

                                $obj = new stdClass();

                                func($obj);

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

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

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

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

                                            Профайлер есть, создает в cachegrind:
                                            xdebug.profiler_enable = 1
                                            xdebug.profiler_output_dir = "/tmp/php"
                                              0
                                              попробую встретится с ним второй раз, хорошо.
                                          0
                                          не ясно преимущество использования лямбда-функций при обходе массивов, ведь код в create_function будет интерпретироваться во время выполнения и не попадет в кэширующий механизм.
                                            0
                                            Код, похоже, оптимизируется, хоть и не кешируется. Я делал замеры быстродействия eval vs create_function, последняя конструкция работает явно быстрее.
                                              0
                                              <?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 добавляет некоторую задержку.
                                                0
                                                Какой кеш кода вы использовали?
                                                  0
                                                  eaccelerator, но вообще это это не имеет значения, т.к. при выполнении скрипта в консоли результаты примерно те же. этот тест не кеширующего механизма, а интерпретатора пхп, кеширование пяти строк 300000 итераций мало что даст.
                                                    0
                                                    eaccelerator, помимо кеширования, делает ещё и оптимизацию. Значит что-то изменилось в датском королевстве, раз eval стал примерно равен create_function на eaccelerator.
                                                      0
                                                      вполне логично, что их эффективность примерно одинакова, в обоих случаях производится интерпретация и выполнение непредсказуемого кода
                                                        0
                                                        Конечно логично, но факт остаётся фактом — около 1.5 года назад разница в скорости была существенной.
                                                  0
                                                  уже умудрился разогнать ваш пример в почти 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
                                                    0
                                                    вру, не в 100 а в 10 =)
                                              0
                                              Спасибо, интересно почитать.
                                              Конечно, есть и вопросы, например, почему LigHTTPd, а не nginx?
                                              Opcode Cacher? Xcache? :)
                                                0
                                                nginx менее production-grade. Хоть и чуть шустрее чем lighttpd, но куда менее гибок и удобен в настройке. Имхо.
                                                  +2
                                                  А приведите пример, пожалуйста, почему Вы так считаете ?
                                                  • НЛО прилетело и опубликовало эту надпись здесь
                                                      0
                                                      если мне не изменяет мой склероз, то Игорь рассказывал о неком иностранце (который русского не знает), который по _русским_ докам легко смог настроить nginx.
                                                      • НЛО прилетело и опубликовало эту надпись здесь
                                                  +1
                                                  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 вообще страннен, классы надо делать статическими, если нужно, а не если можно.
                                                    0
                                                    1. shmop явно неудобен. На shm_* посмотрю, интересное замечание, спасибо
                                                    2. чтобы всё было подконтролем, в независимости от того что решат сделать дефолтным в следующей поставке php ;)
                                                    3. PDO_* работает конечно медленнее чем mysql, т.к. он является для него оберткой. С транзакциями в MySQL при постоянных подключениях есть одни огромные грабли - нужно в конце скрипта не забывать транзакции откатывать или коммитить. Потому что сам он этого делать уже не будет (т.к. коннект не рвётся)
                                                    5. Я в общем-то и написал "не пытайтесь ничего скоприовать по ссылке пока это действительно не будет необходимым" ;).
                                                    6. Просто на моих глазах было много программистов - которым уж очень нужно было всегда создавать экземпляры классов... Даже для factory делали.
                                                      0
                                                      3. ага, а любое действие, которое нужно "не забыть" - это уже ошибка, ибо должно делаться автоматом.
                                                      и, самое главное, нельзя полагаться на то, что выполнение вообще дойдет до вашего "не забытого" закрытия(commit/rollback т.е.) транзакции, т.к. скрипт может быть убит или самоубиться по разным, часто не зависящим от него причинам, сильно надежнее все же без pconnect жить.
                                                        0
                                                        я потестирую транзакции, возможно модель постоянных соединений в PDO_MYSQL работает несколько по-иному.
                                                          0
                                                          Это конечно, полагаться на то, что скрипт "доживёт" до конца в PHP — большая ошибка, не настролько он надёжен. Но проблемы с транзакциями на persistent (кстати, исключительно внутри хранимых процедур, если не ошибаюсь) с умиранием скрипта и забытыми коммитами не связаны.
                                                            0
                                                            не исключительно, транзакция будет висеть открытой пока соединение не закроется или timeout или commit/rollback.
                                                            а вот умирание скрипта с этим пожалуй не связано дествительно, ибо в случае умирания скрипта разницы между persistent и обычным не будет, тут я не совсем по делу да :)
                                                          0
                                                          3) PDO является обёрткой для MySQL API, так же как и mysql_* и mysqli_*. А транзакции, это, безусловно, совсем не грабли, иногда это необходимость (в некоторых случаях хватает и LOCK) и COMMIT/ROLLBACK надо делать не в конце скрипта, в конце транзакции. И проблемы связаны (увы) не с забытыми коммитами.
                                                            0
                                                            зато PDO позволяет малой кровью перейти, например, с PostgreSQL на MySQL. К тому же мне особо импонирует возможность параметризованных запросов (SELECT * FROM t1 WHERE foo = ?), чего нет в нативном mysql_*, и, как следствие, голова не болит о http request parameters escaping.
                                                              0
                                                              Вы, кажется, не поняли о чём я пишу — о некорректной работе транзакций с persistent connection. PDO вам не позволит перейти на PostgreSQL, если вы с самого начала не озаботились тем, чтобы использовать универсальный синтаксис.
                                                                0
                                                                вообще-то я про скорость PDO vs "стандартный старенький extension mysql". Выбирая между PDO и нативным extension, я выбираю PDO :-)
                                                                  0
                                                                  Тема этого поста — скорость, вот я и высказался. Так что, в плане скорости, я PDO не выбираю. Тем более достоинство одно — быстрая смена базы при **определённых условиях**.
                                                        +1
                                                        Спасибо автору!
                                                        Одно добавление из моего личного опыта. У меня нет столько опыта, чтобы быть экспертом во всех областях. Поэтому я использую стандартные настройки сервера и программ, общие правила по написанию кода, не стараюсь добиваться максимальной производительности от функции. Два критерия хорошо кода - понятность и красота :) В результате 80% производительности определяется тем, как спроектирована система. Не бойтесь потратить ваше время на обдумывание и проектирования.
                                                          0
                                                          Категорически против.
                                                          Никогда не тратьте время на предварительное проектирование: в определенный момент разработка встает колом по причине "недостаточно проработанной архитектуры системы". Код должен сам говорить, где хорошо, а где плохо. TDD вам в руки. ;-)
                                                            0
                                                            TDD и отсутствие проектирования архитектуры не имеют между собой ничего общего. Всегда нужно сначала думать а потом делать, иначе ничего хорошего не выйдет. Практики TDD же позволяют сначала разрабатывать тесты, а уж потом писать для них код.

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

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

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

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

                                                                  Грамотный подсчет ;)
                                                                    0
                                                                    <?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 раз. И читаемость повыше для несложных манипуляций.
                                                                      0
                                                                      попробовал и ваш пример. Получилось в 3 раза. Ладно победили. array_walk аутсайдер, хоть и удобен в некоторых случаях (не меняет курсор в массиве и тп). Тем не менее многие другие функции array_* в пхп вообще сложновато без сноровки реализовать foreach-ем. Сортировку, например.
                                                                        0
                                                                        Согласен, функции array_* очень часто выручают и работают сильно быстрее, чем самописные аналоги. Поди не на php написаны :)
                                                                      0
                                                                      Ахринительно полезная статья. Искренне благодарен.
                                                                        0
                                                                        Автор молодец, что потрудился и написал много полезных вещей для php-программистов (начинающих и не очень), но позволю себе заметить, что со знанием принципа работы lighttpd+php+fascgi у него пробел.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                                                                                                          Тем не менее мнение о PHP осталось сдержанно-холодное, но не гневное. Я правда не могу придумать себе сейчас такую задачку, в которой мой выбор пал бы снова на него, но зато глядя на него можно увидеть действительно потрясающий питон =)))))) Не было бы сравнения — не получилось бы))
                                                                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                                                                    0
                                                                                                    Работа полезная, спасибо.

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

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

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

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

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

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

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

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

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

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

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


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

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

                                                                                                                  Самое читаемое