Pull to refresh

Комментарии к статье «Кропотливая оптимизация PHP-приложений»

Reading time4 min
Views1K
Здравствуйте,

Странно, что Хабрахабр не пускает это сообщение как комментарий к топику mocksoul об оптимизации РНР: www.habrahabr.ru/blog/webdev/19129.html. Наверное, слишком длинное. :)


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

1. «В общем когда я делал новый проект — была цель — не менее 50 запросов в секунду на захудалом Celeron 2.6GHz.» Такие цели серьезный программист должен прятать от работодателей далеко-далеко. :) Цель — реализация бизнес-требований. Количество запросов в секунду — это вопрос требований к системе, но далеко не самый важный. Компаниям значительно проще потратить 5-10 тысяч долларов на пару серверов, чем (долго) искать, (чем-то) удерживать и переплачивать 1-2 тысячи каждый месяц программисту, который способен на такие чудеса. :) К сожалению.

2. «LigHTTPd. Под линуксом. Со включенным sys-epoll.» У epoll есть серьезные недостатки перед kqueue. Это и отсутствие process, AIO и timer watching, и поддержка только атомарных событий. Как я понимаю, Linux был выбран исходя из того, что «так сложилось»?

3. «PHP5. Через FastCGI.» К сожалению, PHP не до конца FCGI-compatible, и Если все fcgi-процессы будут заняты единомоментно и закончится backlog, и нет поверх него некоего слоя-менеджера запуска дополнительного пула, то он просто замолкнет — до жесткого перезапуска. Проверить можно запуском ab -n 100000 -c (PHP_FCGI_CHILDREN+1) localhost. Допускаю, что есть реализации, не страдающие подобным. Если знаете, буду благодарен.

4. "'--with-gdbm'". На фоне прочих --without включение gdbm выглядит скорее ошибкой, чем задумкой. Или используете? Это очень неплохое решение для хранения отживших в shm данных.

5. "'--without-mysqli'". >:o А как же prepared statements, multiquery?

6. «PHP_FCGI_CHILDREN» => «32» У меня достаточно давно был опыт с legacy-системой, где код был настолько ужасен, что довольно дорогой сервер складывался на 10-ти параллельных клиентах. Спасла быстрая покупка дополнительной планочки памяти :) и увеличение PHP_FCGI_CHILDREN до максимума, который можно было там позволить — 256. Позже система была перепроектирована, переписана, и пул снижен до 32.

7. «просим убить поток и создать новый через энное количество запросов» — это значение довольно просто посчитать. Если учесть, что для FCGI имеет место affinity (при поллинге), то наиболее удачным вариантом будет полностью обслужить одного клиента в пределах его keep-alive, а потом перезапуститься. Берем количество хитов по php, делим на количество хостов и получаем среднее значение запусков php / визит, увеличиваем его в «магическое» число раз — я беру 1.618, чтобы поглотить первое отклонение. Обычно получается что-то порядка 600-1100.

8. «Пишем и крутим в голове мысли о том как что-то сделать более разумным и быстрым сразу.» Нет, нет и нет! Пишем, проверяем, что работает, потом прогоняем через APD / Xdebug и лечим только то, что нуждается в лечении! Аналогично назначаются индексы в таблицах, кэширование и т.п.

9. «Вам, наверное, почти не нужно будет использовать require и include. В основном — require_once и include_once.» Они примерно в 3-11 раз медленнее. Наиболее удачный вариант — хорошо документируемая карта подключений. Позже, конечно, opcode-кэшер соберет все файлы в одно, но и для первого запуска неплохо.

10. «учимся использовать array_* функции в пхп. Особенно лямбда-функции» Минусы lambda-функций: ухудшение читаемости, хранение каждого экземпляра в global namespace (ваш пример — это именно тот момент, когда создается count($arr) экземпляров), невозможность отлова ошибок на compile-time и т.п. Этого уже достаточно.

11. «foreach ($arr as $key => &$val) {… }». Это уже неактуально. Можно убедиться, вставив в каждую итерацию memory_get_usage().

12. «is_null() — придумана идиотом». А www.php.net/manual/en/types.comparisons.php придумана разработчиками РНР.

13. «Всё просто — если владеете сервером — используйте постоянные подключения!» А вы используете ignore_user_abort() / register_shutdown_function()? Постоянные соединения — это очень, очень опасно! Очень легко получить lockout. Вместо этого лучше использовать либо SQL Relay / pgpoll, либо еще какой-то сторонний менеджер пула подключений.

14. «Скрипт абсолютно нестабилен и заточен под один проект.» Как-то раз я пробовал реализовать билд-менеджер, который вытаскивал все зависимости, сбивал все в один файл на основе switch, тут же пропускал его через энкодер и сохранял в production. Было прикольно. Спасибо, что натолкнули на мысль снова таким воспользоваться. :)

15. «В my.cnf пишем query_cache_size = 100M». Да, доки читаем. Особенно www.mysqlperformanceblog.com/2007/03/23/beware-large-query_cache-sizes. В принципе, в 100М при средней нагрузке будет относительно нормальная расхитовка, но уменьшив до 32-48М можно уменьшить конечный оверхед и сэкономить память под более важные настройки.

16. «Храните в нём все что только можно». Да, мы для интересу хранили там time() c ttl 1 секунда — при плотности запросов больше 600 в секунду получается выигрыш. :)

17. «Не используйте IO в файловую систему для этого — лучше память.» Довольно нередко предел системы — это как раз память. Когда оптимизировано уже все, что можно, код начинает просто упираться в количество процессов. Тогда начинаешь бороться за память, и ситуацию может спасти хороший NAS — это ~2000 Мbps (250М в секунду), что, конечно, несравнимо с памятью, но уже неплохо, а память обычно нужна right here и right now.

18. «Тем не менее многие другие функции array_* в пхп вообще сложновато без сноровки реализовать foreach-ем. Сортировку, например.» Есть прецеденты обгона по скорости встроенного sort()-a функциями, написанными на PHP! :) Просто sort() реализует quicksort как самое общее решение, а для частных случаев есть более быстрые сортировки. К примеру, если нужно сортировать числа, или natural case.

Надеюсь на интересный ответ.
Спасибо за статью! :)
"
Tags:
Hubs:
Total votes 10: ↑10 and ↓0+10
Comments6

Articles