Php оптимизация программ на php


Содержание

Php оптимизация программ на php

Частная коллекция качественных материалов для тех, кто делает сайты

  • Фотошоп-мастер2000+ уроков по фотошопу
  • Фото-монстр300+ уроков для фотографов
  • Видео-смайл200+ уроков по видеообработке
  • Жизнь в стиле «Кайдзен» Техники и приемы для гармоничной и сбалансированной жизни

В этом разделе помещены уроки по PHP скриптам, которые Вы сможете использовать на своих ресурсах.

Фильтрация данных с помощью zend-filter

Когда речь идёт о безопасности веб-сайта, то фраза «фильтруйте всё, экранируйте всё» всегда будет актуальна. Сегодня поговорим о фильтрации данных.

Контекстное экранирование с помощью zend-escaper

Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.

Подключение Zend модулей к Expressive

Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.

Совет: отправка информации в Google Analytics через API

Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.

Подборка PHP песочниц

Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.

Совет: активация отображения всех ошибок в PHP

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

Агент

PHP парсер юзер агента с поддержкой Laravel, работающий на базе библиотеки Mobile Detect.

Php оптимизация программ на php

Одним из основных критериев успешности любого интернет-ресурса является скорость его работы и с каждым годом пользователи становятся всё более и более требовательными по этому критерию. Оптимизация работы php-скиптов — это один из методов обеспечения скорости работы системы.

В этой статье я бы хотел представить на суд общественности свой сборник советов и фактов по оптимизации скриптов. Сборник собирался мною достаточно долго, основан на нескольких источниках и личных экспериментах.

Почему сборник советов и фактов, а не жестких правил? Потому что, как я убедился, не существует «абсолютно правильной оптимизации». Многие приёмы и правила противоречивы и выполнить их все невозможно. Приходиться выбирать совокупность методов, которыми приемлемо пользоваться без ущерба безопасности и удобности. Я занял рекомендательную позицию и поэтому у меня советы и факты, которые Вы можете соблюдать, а можете и не соблюдать.

Что бы не было путаницы, я разделил все советы и факты на 3 группы:

  • Оптимизация на уровне логики и организации приложения
  • Оптимизация кода
  • Бесполезная оптимизация

Группы выделены условно и некоторые пункты можно отнести сразу к нескольким из них. Цифры приведены для среднестатистического сервера (LAMP). В статье не рассматриваются вопросы связанные с эффективностью различных сторонних технологий и фреймворков, так как это тема отдельных дискуссий.

Оптимизация на уровне логики и организации приложения

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

  • Постоянно профилируйте свой код на сервере ( xdebug ) и на клиенте ( firebug ), что бы выявить узкие места кода
    Следует отметить, что профилировать надо и серверную, и клиентскую часть, так как не все серверные ошибки можно обнаружить на самом сервере.
  • Количество, используемых в программе пользовательских функций, никак не влияет на скорость
    Это позволяет использовать в программе бесчисленное число пользовательских функций.
  • Активно используйте пользовательские функций
    Положительный эффект достигается за счёт того, что внутри функций операции ведутся только с локальными переменными. Эффект этого больше, чем расходы на вызовы пользовательских функций.
  • «Критически тяжёлые» функции желательно реализовать на стороннем языка программирования в виде расширения PHP
    Это требует навыков программирования на стороннем языке, что значительно увеличивает время разработки, но в тоже время позволяет использовать приёмы вне возможности PHP.
  • Обработка статического файла html быстрее, чем интерпретируемого файла php
    Различие повремени на клиенте может составлять около 1 секунды, поэтому имеет смысл четкое разделение статики и генерируемых средствами PHP страниц.
  • Размер обрабатываемого (подключаемого) файла влияет на скорость
    Примерно на обработку каждых 2 Кб тратиться 0.001 секунды. Этот факт толкает нас на проведение минимизации кода скриптов при перенесении на рабочий сервер.
  • Старайтесь не использовать постоянно require_once или include_once
    Эти функции нужно использовать при наличии возможности повторного считывания файла, в остальных случаях желательно использовать require и include .
  • При ветвлении алгоритма, если имеются конструкции, которые могут не обрабатываться и их объём порядка 4 Кб и более, то более оптимально их подключать при помощи include.
  • Желательно использовать проверку отправляемых данных на клиенте
    Это вызвано тем, что при проверке данных на стороне клиента, резко снижается количество запросов с неверными данными. Системы проверки данных на клиенте строятся в основном с использованием JS и жестких элементов формы (select).
  • Желательно большие конструкций DOM для массивов данных строить на клиенте
    Это очень эффективный метод оптимизации при работе с отображением большого объёма данных. Суть его сводится к следующему: на сервере подготавливается массив данных и передаётся клиенту, а построение конструкций DOM предоставляется JS функциям. В результате нагрузка частично перераспределяется с сервера на клиент.
  • Системы, построенные на технологии AJAX, значительно быстрее, чем системы, не использующие эту технологию
    Это вызвано уменьшением объёмов вывода и перераспределением нагрузки на клиента. На практике скорость систем с AJAX в 2-3 раза выше. Замечание: AJAX в свою очередь создаёт ряд ограничений на использование других методов оптимизации, например, работа с буфером.
  • При получение post-запроса всегда возвращайте что-нибудь, можно даже пробел
    Иначе клиенту будет отправлена страница ошибки, которая весит несколько килобайт. Данная ошибка очень часто встречается в системах, использующих технологию AJAX.
  • Получение данных из файла быстрее, чем из БД
    Это во многом вызвано затратами на подключение к БД. К моему удивлению, огромный процент программистов маниакально хранят все данные в БД, даже когда использование файлов быстрее и удобнее. Замечание: в файлах можно хранить данные, по которым не ведётся поиск, в противном случае следует использовать БД.
  • Не осуществляйте подключение к БД без необходимости
    По неизвестной мне причине, многие программисты осуществляют подключение к БД на этапе считывания настроек, хотя далее они могут не делать запросов к БД. Это вредная привычка, которая стоит в среднем 0.002 секунды.
  • Используйте постоянное соединение с БД при малом количестве одновременно активных клиентов
    Выгода во времени вызвана отсутствием затрат на подключение к БД. Разница во времени примерно 0.002 секунды. Замечание: при большом количестве пользователей постоянные соединения использовать нежелательно. При работе с постоянными соединениями должен быть механизм завершения соединений.
  • Использование сложных запросов к БД быстрее, чем использование нескольких простых
    Разница во времени зависит от многих факторов (объём данных, настройка БД и пр.) и измеряется тысячными, а иногда даже сотыми, секунды.
  • Использование вычислений на стороне СУБД быстрее, чем вычисления на стороне PHP для данных хранящихся в БД
    Это вызвано тем фактором, что для таких вычислений на стороне PHP требуется два запроса к БД (получение и изменение данных). Разница во времени зависит от многих факторов (объём данных, настройка БД и пр.) и измеряется тысячными и сотыми секунды.
  • Если данные выборки из БД редко меняются и к этим данным обращается множество пользователей, то имеет смысл сохранить данные выборки в файл
    Например можно использовать следующий простой подход: получаем данные выборки из БД и сохраняем их как сериализованный массив в файл, далее любой пользователь использует данные из файла. На практике такой метод оптимизации может дать многократный прирост скорости выполнения скрипта. Замечание: При использовании данного метода требуются писать инструменты для формирования и изменения данных хранимых файле.
  • Кэшируйте данные, которые редко меняются, при помощи memcached
    Выигрыш времени может быть весьма значительным. Замечание: кэширование эффективно для статичных данных, для динамичных данных эффект снижается и может быть отрицательным.
  • Работа без объектов (без ООП) быстрее, чем работа с использованием объектов, примерно, в три раза
    Памяти «съедается» также больше. К сожалению, интерпретатор PHP не может работать с ООП также быстро как с обычными функциями.
  • Чем больше мерность массивов, тем медленнее они работают
    Потеря времени возникает из-за обработки вложенности структур.

Оптимизация кода

Данные советы и факты дают незначительны по сравнению с предыдущей группой прирост скорости, но в своей совокупности эти приёмы могут дать неплохой выигрыш времени.

  • echo и print значительно быстрее, чем printf
    Разница во времени может доходить до нескольких тысячных секунды. Это вызвано тем, что printf служит для вывода форматированных данных и интерпретатор проверяет полностью строку на вхождение таких данных. printf используется только для вывода данных, которым нужно форматирование.
  • echo $var.»text» быстрее, чем echo «$var text»
    Это вызвано тем, что движок PHP во втором случае вынужден искать переменные внутри строки. Для больших объёмов данных и старых версий PHP различия по времени заметны.
  • echo ‘a’ быстрее, чем echo «a» для строк без переменных
    Это вызвано тем, что во втором случае движок PHP пытается найти переменные. Для больших объёмов данных различия во времени достаточно заметны.
  • echo ‘a’,’b’ быстрее, чем echo ‘a’.’b’
    Вывод данных через запятую быстрее, чем через точку. Это вызвано тем, что во втором случае происходит конкатенация строк. Для больших объёмов данных различия во времени достаточно заметны. Примечание: это работает только с функцией echo, которая может принимать несколько строк в качестве аргументов.
  • $return=’a’; $return.=’b’; echo $return; быстрее, чем echo ‘a’; echo ‘b’;
    Причина в том, что вывод данных требует некоторых дополнительных операций. Для больших объёмов данных различия во времени достаточно заметны.
  • ob_start(); echo ‘a’; echo ‘b’; ob_end_flush(); быстрее, чем $return=’a’; $return.=’b’; echo $return;
    Это вызвано тем, что вся работа осуществляется без обращения к переменным. Для больших объёмов данных различия во времени достаточно заметны. Замечание: данный прием неэффективен, если вы работаете с AJAX, так как в этом случае данные желательно возвращать в виде одной строки.
  • Используйте «профессиональную вставку» или ?> a b быстрее, чем
    Статические данные (вне программного кода) обрабатываются быстрее, чем вывод данных PHP. Этот прием называется профессиональной вставкой. Для больших объёмов данных различия во времени достаточно заметны.
  • readfile быстрее, чем file_get_contents , file_get_contents быстрее, чем require , а require быстрее, чем include для вывода статического контента из отдельного файла
    По времени считывания пустого файла колебания от 0.001 для readfile до 0.002 для include .
  • require быстрее, чем include для интерпретируемых файлов
    Замечание: при ветвлении алгоритма, когда есть возможность не использовать интерпретируемый файл, надо использовать include , т.к. require подключает файл всегда.
  • if (. ) <. >else if (. ) <> быстрее, чем switch
    Время зависит от количества веток.
  • if (. ) <. >else if (. ) <> быстрее, чем if (. ) <. >; if (. ) <>;
    Время зависит от количества веток и условий. Необходимо использовать else if везде, где это возможно, так как это самая быстрая «условная» конструкция.
  • Наиболее часто встречающиеся условия конструкции if (. ) <. >else if (. ) <> надо помещать в начале ветвления
    Интерпритатор просматривает конструкцию сверху вниз, пока не найдет выполнение условия. Если интерпретатор находит выполнение условия, то остальныю часть конструкции он не просматривает.
  • x = sizeOf($array); for($i = 0; $i быстрее, чем for($i = 0; $i
    Это вызвано тем, что во втором случае операция sizeOf будет выполнятся при каждой итерации. Время разницы выполнения зависит от числа элементов массива.
  • x = sizeOf($array); for($i = 0; $i быстрее, чем foreach($arr as $value) <. >для не ассоциативных массивов
    Разница во времени значительна и увеличивается при увеличении массива.
  • preg _replace быстрее, чем ereg_replace , str_replace быстрее, чем preg_replace , но strtr быстрее, чем str_replace
    Разница во времени зависит от объёма данных и может достигать нескольких тысячных секунд.
  • Функции работы со строками быстрее, чем регулярные выражения
    Это правило является следствием предыдущего.
  • Удаляйте уже ненужные переменные-массивы для освобождения памяти.
  • Старайтесь не использовать подавление ошибок @
    Подавление ошибок производит ряд очень медленных операций, а так как частота повтора может быть очень большой, потери скорости могут быть значительными.
  • if (isset($str<5>)) <. >быстрее, чем if (strlen($str)>4)
    Это вызвано тем, что вместо функции для работы со строками strlen используется стандартная операция проверки isset .
  • 0.5 быстрее, чем 1/2
    Причина в том, что во втором случае выполняется операция деления.
  • return быстрее, чем global при возвращении значения переменной из функции
    Это вызвано тем, что во втором случае создаётся глобальная переменная.
  • $row[‘id’] быстрее, чем $row[id]
    Первый вариант быстрее в 7 раз.
  • $_SERVER[’REQUEST_TIME’] быстрее, чем time() для определения времени запуска скрипта
    Причина в том, что в первом случае нет использования функции.
  • if ($var===null) <. >быстрее, чем if (is_null($var))
    Причина в том, что в первом случае нет использования функции.
  • ++i быстрее, чем i++ , —i быстрее, чем i—
    Это вызвано особенностями ядра PHP. Разница по времени менее 0.000001, но если у Вас данные процедуры повторяются тысячи раз, то присмотритесь к данной оптимизации.
  • Инкремент инициализированной переменой i=0; ++i; быстрее, чем не инициализированной ++i
    Разница по времени около 0.000001 секунды, но из-за возможной частоты повтора следует помнить данный факт.
  • Использование «отработавших» переменных быстрее, чем объявление новых
    Или перефразирую иначе – Не создавайте лишних переменных.
  • Работа с локальными переменными быстрее, чем с глобальными, примерно, в 2 раза
    Хоть и разница во времени менее 0.000001 секунды, но из-за высокой частоты повторения следует стараться работать с локальными переменными.
  • Обращение к переменной напрямую быстрее, чем вызов функции, внутри которой определяется эта переменная в несколько раз
    На вызов функции тратиться примерно в три раза больше времени, чем на вызов переменной.

Бесполезная оптимизация

Ряд методов оптимизации на практике не оказывают большого влияния на скорость выполнения скриптов (выигрыш времени менее 0.000001 секунды). Несмотря на это, такая оптимизация зачастую становиться предметом споров. Я привел данные «бесполезные» факты для того, чтобы вы в последующим не уделяли им особого внимания при написании кода.

  • echo быстрее, чем print
  • include(‘абсолютный путь’) быстрее, чем include(‘относительный путь’)
  • sizeOf быстрее, чем count
  • foreach ($arr as $key => $value) <. >быстрее, чем reset ($arr); while (list($key, $value) = each ($arr)) <. >для ассоциативных массивов
  • Не комментированный код быстрее, чем комментированный, так как уходит дополнительное время на чтение файла
    Весьма глупо уменьшать объём комментариев ради оптимизации, надо просто в рабочих («боевых») скриптах проводить минимизацию.
  • Переменные с короткими названиями быстрее, чем переменные с длинными названиями
    Это вызвано сокращением объёмов обрабатываемого кода. Аналогично предыдущему пункту, надо просто в рабочих («боевых») скриптах проводить минимизацию.
  • Разметка кода с использованием табуляции быстрее, чем с использованием пробелов
    Аналогично предыдущему пункту.

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

Если у Вас возникли вопросы, то для скорейшего получения ответа рекомендуем воспользоваться нашим форумом

Оптимизация PHP скриптов

Отличие PHP от других языков программирования, например, C++, Pascal и т.д. заключается в том, что исходный код программы на php при каждом обращении к скрипту интерпретируется по-новой. Поэтому важно научиться правильно (оптимально) составлять код программ.

  • используем короткие имена переменных (не более 4 символов)
  • используем sizeof() вместо count()
  • выносим определение размера массива за пределы цикла
  • элементы масива с числовыми индексами лучше перебирать через for/while
  • элементы ассоциативного масива лучше перебирать через foreach
  • доступ к элементу одномерного ассоциативного массива по имени, не заключенному в кавычки, тормозит процесс на треть
  • не создаем лишних переменных. Вместо $x=1; $y=2; $z=x+y; пишем $z=1+2
  • выносите $переменные из «текстовых строк» и вместо echo » Итого: $cnt»; используйте echo ‘ Итого: ‘.$cnt;
  • для чтения файла file() быстрее, чем fopen+цикл

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

Но, сделаю замечание, если есть определенный набор скриптов, который подключается гарантированно всегда (базовая библиотека), то их лучше всего объеденить в один файл. Это увеличит скорость их подключения.

Проведя ряд экспериментов, можно получить интересный результат: если в функцию передавать глобальные переменные в виде параметров функции, а не через директиву global, то работа локального участка кода php-скрипта увеличивается в 2 раза.

Чем меньше трафик от сервера к клиенту, чем быстрее загружаются страницы. Следующий эксперимент позволил ускорить работу php-скриптов в 4 — 20 раз! Действительно, впечатляющие показатели. Чтобы добиться такого ускорения, нужно использовать всего два оператора PHP:

  • @ob_start(«ob_gzhandler»); — в самом начале скрипта.
  • @ob_end_flush(); — в завершении скрипта.

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

Если клиентское приложение поддерживает стандарты передачи-приема сжатой информации, то получаемая информация из буфера будет сжата, что сэкономит немного трафика и уменьшит время получения ответа от сервера.

HOWTO по оптимизации PHP

PHP очень быстрый язык программирования, но есть еще множество способов оптимизации, помимо оптимизации кода.

В этом материале мы объясним, почему оптимизация PHP захватывает собой гораздо больше факторов, нежели простая оптимизация кода, и почему настройка PHP требует понимания, каким образом работает PHP относительно других компонентов вашего сервера. Также мы займемся выявлением узких мест, связанных с этими компонентами и устранением их. Также мы затронем вопросы оптимизации ваших PHP скриптов, чтобы они работали еще быстрее.

Достижение высокой производительности

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

В примере ниже, A.php спринтер настроен для быстрого запуска, а B.php бегун марафона может бегать трусцой, почти с той же самой скоростью. При низкой загрузке, A.php существенно быстрее, но как только трафик начинает увеличиваться, работа B.php снижается лишь немного, тогда как A.php выдыхается.

Давайте возьмем более реалистичный пример для дальнейших рассуждений. Предположим, нам необходимо написать скрипт, который должен прочитать файл размером 250 кб и сгенерировать HTML, резюмирующий информацию из файла. Мы пишем два сценария, которые делают одно и тоже: hare.php, который читает файл в память целиком и обрабатывает его за один проход, и tortoise.php, который читает файл построчно не сохраняя в памяти информации, больше чем одна строка. Tortoise.php будет медленнее, потомучто использует многократное чтение, требует большего количества системных вызовов.

Hare.php требует 0.04 секунды центрального процессора, а также 10 мб памяти. Tortoise.php требует 0.06 секунд процессорного времени и 5 мб памяти. Сервер располагает 100 мб свободной памяти и процессор на 99% свободен. Предположим, что никакой фрагментации памяти не происходит (для упрощения).

При 10 одновременных запусках скрипта, hare.php исчерпает память (10 х от 10 до 100). В этой точке, tortoise.php все еще будет иметь в своем распоряжении 50 мб свободной памяти. 11 запуск hare.php приведет к уменьшению производительности, поскольку система начнет использовать виртуальную память. При этом, его первоначальная скорость может упасть более чем в половину. Каждый запуск hare.php на данный момент занимает 0.08 секунд процессорного времени. Тем временем tortoise.php все также будет занимать свое процессорное время 0.06 секунд.

В таблице ниже, самый быстрый сценарий выделен полужирным:

Соединения CPU секунды при запуске 1 скрипта CPU секунды при запуске 10 скриптов CPU секунды при запуске 11 скриптов
Hare.php 0.04 0.40 0.88 (свободная память закончилась)
Tortoise.php 0.06 0.60 0.66

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

Узкие места

Пример hare и tortoise (зайца и черепахи) показал нам причины узких мест. С бесконечной оперативной памятью hare будет быстрее всегда, чем tortoise. К сожалению, вышеупомянутая модель слишком упрощена, и есть еще много других узких мест, препятствующих работе, помимо оперативной памяти:

Ваша сеть, вероятно, самое узкое место. Например, вы говорите, что у вас 10 Мбит связь с интернетом, по которой вы можете скачать 1 мб данных в секунду. Если каждая страница у вас занимает 33 кб, то обычные 33 страницы в секунду будут занимать весь ваш канал.

Более тонкие узкие места в сети это скорость отклика, например, сервера имен (DNS), или адресация нужного количества памяти для программного обеспечения сети.

Центральный процессор

Если вы контролируете загрузку центрального процессора, то увидите, что пересылка обычных HTML страниц вообще не будет обременять процессор, и, в данном случае, самым узким местом будет сеть. Однако, для сложных динамических web-страниц, производимых PHP, скорость вашего процессора будет ограничивающим фактором. Наличие нескольких процессоров или фермы серверов может значительно снизить подобное ограничение.

Shared Memory (общедоступная память)

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

Файловая система

Доступ к жесткому диску может быть в 50-100 раз медленнее, чем доступ к данным в оперативной памяти. Кэширование файлов с использованием оперативной памяти могут снизить данное ограничение. Однако, в условиях небольшого количества памяти для системного кэша, работа будет замедляться. Системные файлы так же могут быть сильно фрагментированными, замедляя дисковый доступ. Частое использование симлинков на UNIX системах также приводят к замедлению.

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

Управление процессами

В некоторых операционных системах, например, в Windows, создание нового процесса это медленная операция. Это означает, что CGI процесс, вызываемый для каждой операции, будет работать значительно медленнее. Запуск PHP в multi-threaded (в виде модуля) режиме должно увеличить скорость ответа (примечание: старые версии PHP неустойчивы в данном режиме).

Избегайте переполнения вашего сервера множеством ненужных процессов. Например, если ваш сервер предназначен только для обслуживания сети, избегайте запуска (или даже вообще установки) X-Windows. На Windows-системах избегайте запуска Microsoft Find Fast (компонент офиса), а также всякого рода screensaver’ов. Потомучто все это заканчивается 100% использованием процессора.

Некоторые программы вы можете рассмотреть к удалению, включая неиспользуемые сетевые протоколы, серверы почты, сканеры антивирусов, аппаратные драйверы для мыши, инфракрасного порта и так далее. На Unix: я подразумеваю, что вы общаетесь со своим сервером посредствам SSH. В этом случае, вы можете рассмотреть к удалению следующее:

  1. демоны, например, telnetd, inetd, atd, ftpd, lpd, sambad
  2. sendmail для поступающей почты
  3. portmap для NFS
  4. xfs, fvwm, xinit, X

Также вы можете отключить запуск некоторых программ при загрузке, изменяя файлы запуска, которые обычно хранятся в /etc/init* или /etc/rc*/init* директории.

Также рассмотрите задачи, которые запускаются по крону. Посмотрите, можно ли их удалить или перенести на непиковые периоды.

Соединение с другими серверами

Если ваш сервер требует услуг, выполняющихся на других серверах, это тоже может стать узким местом. Самый общий пример это медленный сервер базы данных, который обслуживает много сложных SQL запросов от разных серверов сети.

Когда начинать оптимизацию?

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

Мой совет преже чем начинать проектирование приложения, сделайте некоторые основные эталонные тесты аппаратных средств и программного обеспечения, чтобы получить чувство максимальной работоспособности, которую вы могли бы достигнуть. Тогда, когда вы проектируете и кодируете приложение, держите желательные рабочие параметры в памяти, потому что на каждом этапе пути вам придется идти на компромиссы между производительностью, функциональностью, защитой и гибкостью.

Также выберите хорошие испытательные данные. Если ваша база данных, как ожидается, будет хранить только 100 000 записей, избегайте тестирования ее только со 100 записями, вы будете потом об этом сожалеть. Это когда-то случилось с одним из программистов в моей компании: мы обнаружили медленный код значительно позже, потратив много времени впустую, поскольку пришлось переписать большую часть кода, который работал, но не масштабировался.

Настройка вашего сервера для PHP


Далее, мы рассмотрим с вами, как оптимизировать работу с PHP двух самых распространенных web-серверов, Apache 1.3 и IIS.

Разработчики PHP заявляют, что нет никакой разницы в скорости и преимуществах масштабирования при использовании Apache 2.0 над Apache 1.3, особенно, если PHP установлен в виде модуля.

Apache 1.3/2.0

Этот сервер доступен на Unix и Windows платформах, это самый популярный сервер в мире. Apache 1.3 использует pre-forking (предразветвления) модель для обслуживания сети. После старта, сервер создает дочерние процессы для обслуживания каждого HTTP запроса. Родительский процесс действует как ангел-хранитель, проверяя, что все дочерние процессы работают правильно и координирует их действия. Чем больше HTTP запросов, тем больше дочерних процессов будет порождено, чтобы их обработать. Поскольку HTTP запросы начнут замедляться, родительский процесс уничтожает неактивные дочерние процессы, освобождая ресурсы для новых процессов. Красота данного подхода в том, что это делает Apache чрезвычайно устойчивым. Даже если дочерний процесс рушится, родительский и другие дочерние процессы будут изолированы от сбойного дочернего процесса.

Модель предразветвления не настолько быстра, как другие решения. Но, что касается меня, то это является суматохой ни о чем, на сервере, обслуживающем PHP сценарии, потомучто другие узкие места дадут сбой раньше, чем проблемы Apache станут существенными для сервера. Ошибкоустойчивость и надежность Apache более важный фактор.

Apache 2.0 может работать в модульном режиме (multi-threaded). Мои эталонные тесты показали, что преимуществ этого режима не так уж много. Также будте готовы к тому, PHP расширения несовместимы, например GD и IMAP. Проверено на Apache 2.0.47 (23 октября 2003).

Apcahe сконфигурирован при помощи файла httpd.conf. Следующие параметры особенно важны при настройке дочерних процессов:

Максимальное число дочерних процессов, которые может создать сервер. Значение поумолчанию 256 означает, что одновременно может быть обработано 256 HTTP запросов. Любые дальнейшие запросы будут поставлены в очередь.

Количество дочерних процессов, которые будут созданы сразу после старта сервера.

Число неактивных дочерних процессов, которые должны быть созданы. Если число неактивных процессов падает ниже этого числа, то 1 ребенок создается первоначально, 2 на следующую секунду, 4 еще через секунду, и так далее, пока не будет создано 32 дочерних процесса с интервалом в секунду.

Если создано больше, чем данное число дочерних процессов, то эти дополнительные процессы будут остановлены.

Устанавливает какое число HTTP запросов ребенок должен обработать перед завершением. Если вы устанавливаете ее в , то дочерний процесс никогда не умирает. Установите его в пределах от 100 до 10000, если вы подозреваете утечки памяти или неправильно использование ресурсов.

Для больших сайтов наилучшими значениями будут близкие к этим:

  1. MinSpareServers 32
  2. MaxSpareServers 64

Apache под Windows ведет себя иначе. Вместо того, чтобы использовать дочерние процессы, Apache использует треды. Вышеупомянутые параметры не используются. Вместо этого мы имеем один параметр: ThreadsPerChild который имеет значение поумолчанию 50. эта переменная указывает число тредов, которые могут быть порождены Apache. Поскольку в Winodws есть только один дочерний процесс, то количество HTTP запросов, которые он может обработать, равняется 50. Для серверов сети, которые испытывают более серьезные нагрузки, увеличьте этот параметр от 256 до 1024.

Другие полезные параметры, которые вы можете изменить приведены ниже:

Параметр Поумолчанию Описание
MaxClients 256
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestsPerChild

Определяет объем буфера вывода (в байтах), используемого в TCP/IP соединениях. Этот параметр прежде всего полезен для переполненных или медленных сетей, когда пакеты необходимо буферизировать. В этом случае, установите этот параметр близким к размеру самого большого пересылаемого файла. Один TCP/IP буфер будет создан при соединении.

В оригинале HTTP спецификации, каждый HTTP запрос должен создавать новое соединение с сервером. Keep-alive заголовок был создан, чтобы уменьшить нагрузку на сервер. Параметр keep-alive говорит серверу, чтобы он использовал тоже самое соединение через socket (сокет) для нескольких HTTP запросов.

Если у вас есть отдельные сервер, который обслуживает все изображения (images), то вы можете выключить этот параметр. Подобная техника поможет значительно сэкономить ресурсы сервера.

Количество секунд для удержания сокет-соединения. Это время включает в себя генерацию контента и ответ клиента. Если клиент не реагирует в течение этого времени будет создано новое соединение.

Это значение не должно быть большим, иначе сокет будет простаивать в этот период.

Сокет-соединения будут закончены, как только их количество достигнет этой цифры. Установите большое значение, но меньше MaxClients или ThreadsPerChild.

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

Максимальный размер PUT или POST. нет лимита.

Если вы не требуете DNS поиска и не используете htaccess для настройки отдельных директорий в Apache, вы можете задать:

Если вас не волнует безопасность папок при вызове симлинков, включите FollowSymLinks и выключите SymLinksIfOwnerMatch, чтобы предотвратить дополнительный системный вызов lstat():

Настройка IIS

Параметр Поумолчанию Описание
SendBufferSize Определяется операционной системой.
KeepAlive [on|off] On
KeepAliveTimeout 15
MaxKeepAliveRequests 100
TimeOut 300
LimitRequestBody

Определяет, какое количество памяти отвести для IIS. (Performance Tab).

Управляет полосой пропускав секунду, разделенную по серверам. (Performance Tab).

Управляет процентом процессорного времени, доступного для процесса по серверам. (Performance Tab).

По умолчанию 900 секунд. Установите более низкое значение, если у вас локальная сеть. (Web Site Tab)

В IIS 5 вы можете сжимать динамические страницы, HTML и картинки. Вы можете настроить эти параметры. Значение по умолчанию выключено.

HTTP сжатие нужно включать для всего сервера. Чтобы включить этот параметр нажмите правую кнопку мыши на консоли сервера (не на одном из подсайтов), выберите Свойства (Properties). Нажмите на Вкладке Service, затем выберите Compress application files для компрессии динамических данных, и Compress static files для компрессии статического контента.

Также вы можете изменить, настроенный поумолчанию, уровень изоляции web-сервера. Во вкладке Home Directory в Application Protection вы можете определить уровень изоляции. На высшем уровне изоляции ваш сайт будет работать медленнее, потомучто это будет отдельный процесс от IIS, вто время как запуск сайта в IIS процессе самая высока скорость, но сервер может лечь, если в вашем скрипте есть серьезные ошибки. На данный момент я рекомендую запускать PHP сайты как CGI или с использованием ISAPI совместно с Application Protection установленной в hight (высокая).

Вы также можете использовать regedit.exe для изменения параметров IIS 5, сохраненных в ветке HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesInetinfoParameters.

Настройка производительности исходя из обращений к серверу в день.
Управление полосой пропуска
Управление процессом
HTTP компрессия

Устанавливает количество памяти, которую IIS будет использовать для кэширования своих файлов. Поумолчанию, ISS может использовать 50% установленной в компьютере памяти. Вы можете увеличить этот параметр, если на машине работает только IIS. Значение задается в мегабайтах.

Определяет максимальный размер файла, который может быть кэширован. Размер указывается в байтах. Значение поумолчанию 262,144 (256 кб).

Устанавливает время (в миллисекундах), в течение которого кэшированный объект сохраняется в памяти. Значение поумолчанию 30,000 миллисекунд (30 секунд).

Устанавливает число нитей на процессор. Определяет, сколько CGI приложений может быть запущено одновременно. Значение поумолчанию 4. увеличьте это значение, если вы используете PHP как CGI.

Максимальное количество активных живых соединений (Keep alive), которые ISS поддерживает в очереди соединений. Значение поумолчанию 15, должно быть увеличено к числу одновременных соединений, поддерживаемых вашим сервером. Максимально 255.

Если эти параметры отсутствуют в данной ветке реестра будут использоваться параметры поумолчанию.

Высока производительность в Windows: IIS и FastCGI

После большого тестирования, я считаю, что самая высока производительность PHP в Windows достигается использованием IIS с FastCGI. CGI это протокол для вызова внешней программы из сервера. Это дает не самую высоку скорость, потомучто CGI программа удаляется каждый раз после создания страницы. FastCGI изменяет этот протокол для достижения более высокой производительности, заставляя CGI программу оставаться запущенной после обработки запроса, и многократно использоваться для обработки последующих запросов.

Поскольку установка FastCGI на IIS достаточно сложна, вы должны использовать EasyWindows PHP Installer (http://phplens.com/phpeverywhere/easywindows). Он установит PHP, FastCGI и Turck MMCache для достижения лучшей производительности. Этот инсталлер также может установить PHP для Apache 1.3/2.0.

PHP 4 и Zend Engine

Zend Engine это внутренний компилятор и движек, использованный для создания PHP 4. Созданный Zeev Suranski и Andi Gutmn, Zend Engine это сокращение от их имен. На начальном этапе PHP работал следующим образом:

PHP скрипт загружается в Zend Engine и компилируется в opcode. Opcode это набор низкоуровневых бинарных инструкций. После запуска opcode происходит генерация HTML и передача его клиенту. Opcode удаляется из памяти после выполнения.

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

PHP скрипт загружается в Zend Engine и компилируется в opcode. Opcode может быть оптимизирован с использованием необязательного оптимизатора, названного Zend Optimizer. В зависимости от скрипта, он может увеличить скорость выполнения PHP скрипта до 50%.

Раньше, после выполнения, opcode уничтожался. Теперь вы можете организовать его кэширование, используя несколько альтернативных вариантов: продукты с открытым кодом и Zend Accelerator (раньше известен как Zend Cache), который является закрытым коммерческим продуктом. Только кэшированный opcode совместим с Zend Optimizer и Zend Accelerator. Opcode кэш ускоряет выполнение, удаляя из цепочки загрузку исходного скрипта и его компиляцию. Время выполнения, с использованием кэширования, может улучшиться от 10 до 200%.

ДОПОЛНЕНИЕ:

Где искать инструменты для кэширования opcode?

Zend Accelerator. Это коммерческий продукт, развитый командой Zend Engine. Очень надежный. Искать здесь: http://zend.com.

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

Turck MMCache (http://turck-mmcache.sourceforge.net/) больше не поддерживается. Смотрите eAccelerator, который является развитием mmcache и активно развивается.

Один из секретов высокой производительности состоит не в том, чтобы написать быстрый PHP код, а в том, чтобы кэшировать результаты выполнения скрипта в файл или общую память. Скрипт запускается однажды, генерируемый HTML захватывается и все последующие обращения к скрипту приводят к показу уже готового HTML. Если требуется регулярное обновление данных, то необходимо указать срок жизни для кэшированных HTML. Кэширование HTML это не часть PHP языка или Zend Engine но осуществляется при помощи PHP кода. Существует много классов и библиотек для организации подобного. Одна из них PEAR Cache, о которой мы поговорим в следующей части. Другой распространенный способ библиотека Smarty.

И, наконец, HTML, отдаваемый браузеру клиента, может быть сжат. Это включается добавлением следующего кода вначале вашего скрипта:

Если ваш HTML очень сжимаем, то это может уменьшить размер на 50-80%, сокращая тем самым требования пропускного канала. Другая сторона это необходимость в более мощном процессоре, чтобы эффективно и быстро сжимать страницы.

HTML кэширование с использованием PEAR Cache

PEAR Cache это набор классов для кэширования разнообразных типов данных, включая HTML и картинки.

Самое распространенное использование PEAR Cache это кэширование HTML текста. Чтобы использовать кэширование задействуем Output buffering class, с кэшированием всего выдаваемого текста между функциями start() и end():

Примечание: С тех пор, как я написал эти строки, была создана более продвинутая система кэширования PEAR: Cache Lite (http://pear.php.net/package/Cache_Lite); чтобы узнать об этом подробнее, смотрите memcached (http://www.danga.com/memcached/).

Cache конструктор принимает первым параметром тип драйвера для сохранения кэша. Доступны следующие драйверы: файл, база данных, общая память (смотрите папку: pear/Cache/Container). Тесты Ulf Wendel показывают, что драйвер файл дает наилучшую производительность. Второй параметр это параметры для используемого драйвера. Варианты: cache_dir это папка для сохранения кэшированных данных, filename_prefix уникальная приставка к названию файлов для сохранения кэшированных данных. Что странно, время жизни кэша не является параметром для конструктора.

Для кэширования каких-то данных, вам необходимо сгенерировать уникальный ключ (id) для этих данных. В примере выше, мы использовали md5(«это уникальный ключ!»).

Функция start() использует ключ для поиска кэшированной копии данных. Если контент не был кэширован, функция вернет пустую строку. И все последующие echo и print будут буферизироваться в кэш, до тех пор, пока не встретится функция end().

Функция end() возвращает содержимое буфера и заканчивает буферизацию вывода. Функция end() принимает в качестве первого параметра время жизни кэша. Этим параметром могут быть секунды или Unix таймштамп, указывающий точное время окончания жизни кэша, или установит интервал по умолчанию 24 часа.

Другой способ использования PEAR Cache это сохранение значения переменных или других данных. Для реализации этого используйте основной Cache класс:

Для сохранения используемых данных применяйте функцию save(). Если выбранный вами уникальный ключ уже существует, вы можете использовать функцию generateID(). Объекты и массивы могут быть сохранены благодаря использованию функции serialize() внутри функции save(). Последний параметр это время жизни кэша. Этим параметром могут быть секунды или Unix таймштамп, указывающий точное время окончания жизни кэша, или установит интервал по умолчанию 24 часа. Для получения кэшированных данных используйте функцию get().

Использование тестов производительности

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

Если вы хотите получить наиболее реалистичные тесты производительности вебсервера, вам необходим инструмент, умеющий посылать разнообразные HTTP запросы. На Unix обычные инструментальные средства тестирования включают ab (сокращение от apachebench), который являются частью пакета Apache. И более нового flood (http://httpd.apache.org/test/flood). На Windows NT/2000 вы можете использовать Microsoft’s free Web Application Stress Tool (http://webtool.rte.microsoft.com).

Эти утилиты могут делать параллельные множественные HTTP запросы моделируя тем самым множество клиентов сети, и выдавать вам детальную статистику по завершению теста.


Вы можете контролировать, каким образом ведет себя ваш сервер, поскольку тесты проводятся на основе Unix с использованием «vmstat1«. Он печатает информацию о статусе вашего диска, виртуальной памяти, и загрузки процессора каждую секунду. Альтернативно вы можете использовать «top d 1» который дает вам полноэкранную индикацию всех процессов запущенных и сортированных по степени загрузки процессора каждую секунду.

На Windows 2000 вы можете использовать Performance Monitor или Task Manager для просмотра статистики своей системы.

Если вы хотите проверить специфический аспект вашего кода без необходимости использования HTTP запросов, вы можете написать тест с использованием функции microtime(), которая возвращает текущее время в микросекундах в виде строки. Следующая функции конвертирует это значение в число, подходящее для статистики:

Альтернативно, вы можете использовать специальные инструменты для профелирования: APD (http://www.linuxjournal.com/article.php?s >

Этапы тестирования производительности

Далее, я привожу детали реального теста производительности, созданного для одного из клиентов. В данном случае, клиент хотел гарантированное время отклика 5 секунд для любой PHP страницы, которая не делала сложных SQL запросов. Конфигурация сервера: Apache 1.3.20, PHP 4.0.6 на Red Hat 7.2 Linux. Аппаратное обеспечение: два Pentium III 933 Mhz, 1Gb RAM. HTTP запросы будут обращаться к скрипту testmysql.php. Этот скрипт читает и обрабатывает примерно 20 записей из MySql базы данных, расположенной на другом сервере. Для простоты мы предполагаем, что вся графика грузится с другого сервера.

Как инструмент для тестирования производительности мы использовали ab. Мы задали ab делать 1000 запросов (-n1000), используя 10 одновременных соединений (-c10). Вот результаты:

После запуска теста производительности, он начал контролировать на стороне сервера использование ресурсов с использованием команды «top d 1«. Параметр «d 1» указывает, что необходимо делать задержку в 1 секунду перед обновлением данных. Вывод показан ниже.

Посмотрите на шапку вывода. Результаты показывают, что Apache, на машине с двумя процессорами, отработал с 0% простоя. Это очень плохо. Средняя загрузка составила 9.07 за последнюю минуту (3.29 за последние 5 минут, 1.79 за последние 15 минут). Средняя загрузка это среднее число процессов, готовых быть запущенными. Для двухпроцессорного сервера любая загрузка больше 2, означает, что система будет перегружена процессами. Здесь вы можете видеть тесную связь между загруженностью 9.07 и количеством запущенных процессов (10), которые были определены в тесте ab.

К счастью, мы располагаем большим объемом свободной оперативной памяти, приблизительно 798 160 Мб, никакой виртуальной памяти не используется.

Далее, внизу, мы можем видет процессы, упорядоченные по количеству использования центрального процессора. Самые активные это процессы Apache (httpd). Первая задача httpd использует 7280 Кб памяти и отнимет в среднем 21.2% процессора, и 0.7% оперативной памяти. Колонка STAT показывает статус: R работает, S бездействует, W означает, что процесс выгружен из памяти.

Вышеприведенные цифры показывают нам типичную пиковую нагрузку, мы можем сделать некоторое планирование. Если среднее число загрузки для сервера с двумя процессорами 9.0, и задача отнимает для исполнения примерно одно и тоже время, то слегка загруженный сервер должен быть 9.0/2 процессора = в 4.5 раз более быстрым. Так что HTTP запрос, который обыкновенно занимал 1.283 секунды, при пиковой нагрузке займет примерно 1.283/4.5 = 0.285 секунд.

Для проверки этого, мы делаем тест производительности с 2 одновременными процессами (вместо 10 выше). Получаем 0.281 секунды, что очень близко к предсказанному значению 0.285!

Наоборот, удваивая количество подключений, мы можем предсказать, что среднее время выполнения должно удвоиться с 1.283 до 2.566 секунд. В тестах производительности мы, фактически, получили 2.570 секунд.

Перегрузка при 40 подключениях

После того, как мы запустили тест производительности с 40 запросами, сервер был перегружен с 35% неудачных запросов. При дальнейшем расследовании было обнаружено, что MySql сервер отказывал в запросах с ошибкой Слишком много подключений.

Тест производительности также указал на поведение дочерних процессов Apache. Каждый скрипт PHP использовал 2 постоянных соединения, так, на 40 запросах мы имели 80 постоянных подключений, что значительно ниже значения по умолчанию MySql (max_connections 100). Однако, дочерние процессы Apache, которым не переданы немедленно новые запросы, всеравно удерживают постоянное соединение. Эти неактивные дочерние процессы породили еще более 20 постоянных соединений, которые оказались соломкой, которая сломала спину верблюду.

Исправляем ситуацию

Переведя скрипты на непостоянные соединения, мы устранили эту проблему и получили результат 5.340 секунд. Альтернативное решение состояло в том, чтобы увеличить MySql max_connections выше, чем значение по умолчанию.

Заключение

Вышеупомянутое исследование в очередной раз показывает нам, что оптимизация вашей работы является чрезвычайно сложной. Это требует понимания множества программных систем, включая маршрутизацию сети, стек TCP/IP, количество физической и виртуальной памяти, количество процессоров, поведение дочерних процессов Apache, ваших скриптов PHP и конфигурации базы данных.

В данном случае, код PHP был очень хорошо отлажен и самым узким местом оказался центральный процессор, который вызывал замедление в момент ответа. Поскольку нагрузка возросла, система значительно замедлилась, но находилась у требуемого порога (что является хорошим показателем), пока мы не столкнулись с более серьезным узки местом недостаточным количеством возможных подключений к MySql. Это вызвало многократные ошибки наших скриптов, пока мы не устранили их переходом на непостоянные соединения.

Из вышеприведенных значений, мы можем вычислить какое количество соединений мы можем обработать не выходя за пределы желаемого времени ответа. Предполагая наличе двусторонней сети с временем доступа 0.5 секунд на Internet (0.25 секунд одна сторона), мы можем предсказать:

Поскольку наш клиент хотел время ответа 5 секунд, сервер сможет обрабатывать до 34 одновременных подключений в секунду. Это дает на пиковой нагрузке 34/5 = 6.8 страниц в секунду.

Для получения максимального количества страниц для просмотра в день, мы должны умножить пиковую способность в секунду на 50.000 (эта методика предложена веб-мастерами pair.com, большой хостинговой компанией), что даст нам 340 000 страниц в день.

Оптимизация кода

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

Большинство PHP сценариев просты. Они получают небольшое количество информации о сессии, загружают некоторое количество информации из системы управления контентом или базы данных, форматируют соответствующий HTML и отдают результат своей работы HTTP клиенту. Предположим, что типичный PHP сценарий исполняется 0.1 секунду, время ожидания Internet 0.2 секунды, только 33% времени из этих 0.3 секунд будут использоваться для генерации PHP сценарием ответа. Так, если вы улучшите скорость своего скрипта на 20%, клиент будет видеть, что время ответа сократилось до 0.28 секунд, что является незначительным усовершенствованием. Конечно сервер сможет обработать на 20% больше запросов к одной и той же странице, что увеличивает масштабируемость.

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

Высокие степени оптимизации

Места, где высокая степень оптимизации достижима, находятся внутри циклов while и for, где каждое замедление кода увеличивается в несколько раз из-за их повторения. Лучший способ для понимания этого, это рассмотреть несколько примеров:

Пример 1

Вот вам один из простых примеров, печатающих массив:

Этот код может быть существенно ускорен, если переписать его следующим образом:

Для начала необходимо понять, что выражение $j prop++) примерно в три раза медленнее чем локальная переменная.

  • Увеличение неопределенной локальной переменной примерно в 9-10 раз медленнее, чем предопределенной.
  • Только определение глобальной переменной без ее использования в функции также замедляет работу (примерно на тоже самое время, как и увеличение локальной переменной). PHP, вероятно, делает проверку на существование глобальной переменной.
  • Скорость обращения к методу не зависит от количества методов в классе, потому что я добавил еще более 10 методов в тестовый класс, что не привело к изменениям в скорости.
  • Методы в производных классах работаю быстрее, нежели определенные в базовом классе.
  • Функции с одним параметром вызова, а также с пустым телом занимают по времени столько же, сколько занимают 7-8 операций $localvar++. Вызов подобного метода занимает 15 $localvar++.
  • Дополнение от 11 июля 2004: эти испытания были проведены почти 3 года назад. Я проверил эти данные вновь на версии 4.3.3. Вызов функции теперь занимает 20 $localvar++, а вызов метода 30 $localvar++. Это может быть потому, что $localvar++ стало выполняться быстрее или вызов функция стал медленнее.

    Резюме

    1. Чем больше вы разбираетесь в программном обеспечении, которое вы используете (Apache, PHP, IIS, база данных), и чем глубже ваши знания операционной системы, организации сети, аппаратного обеспечения сервера, тем лучше вы сможете выполнить глобальную оптимизацию вашего кода и вашей системы.
    2. Для PHP скриптов самое узкое место обычно это центральный процессор. Два процессора, вероятно, будут лучше, чем два гигабайта оперативной памяти.
    3. Сборка PHP с параметром configure enable-inline-optimization позволяет сделать максимально быстрый исполняемый файл.
    4. Оптимизируйте вашу базу данных и индексы, которые чаще всего используются в параметре WHERE ваших SQL запросов. ADODB очень популярная библиотека абстрактного доступа позволяет работать в режими оптимизации SQL запросов, где вы можете всесторонне изучить ваши неудачные SQL запросы, а также определить, в каком скрипте они выполняются.
    5. Используйте кэширование HTML, если ваши данные редко меняются. Даже если ваши данные меняются каждую минуту кэширование может помочь, если данные синхронизировать с кэшем. В зависимости от сложности кода, кэширование позволяет улучшить скорость до 10 раз.
    6. Тестируйте производительность вашего сложного кода на ранних этапах (или по крайней мере его опытные образцы), таким образом вы получите чувство ожидаемых параметров работы, прежде чем будет слишком поздно. Попробуйте использовать реалистические количества испытательных данных, чтобы гарантировать должную масштабируемость.
    7. Рассмотрите возможности использования кэширования опкода. Это дает прирост производительности на 10-200% в зависимости от сложности вашего кода. Обязательно сделайте стресс тестирование вашего кода, прежде чем устанавливать оптимизаторы на реально работающий сервер, поскольку некоторые из них более надежны чем другие.
    8. Используйте ob_start() в начале вашего кода. Это даст вам повышение производительности на 5-15%. Вы также можете использовать gzip сжатие для организации быстрых загрузок (это требует дополнительных ресурсов центрального процессора).
    9. Рассмотрите возможность установки Zend Optimizer‘а. Это бесплатное программное обеспечение делает некоторую оптимизацию, но будте внимательны некоторые скрипты фактически замедляются, когда установлен Zend Optimizer. В основном, Zend Optimizer очень полезен, когда ваш код содержит множество циклов.
    10. Оптимизируйте код циклов. Переместите определения, по которым работает цикл перед циклом.
    11. Используйте массивы и строковые функции везде, где это возможно. Они работают значительно быстрее, чем написание аналогичного кода.
    12. Самый быстрый способ связать многократные небольшие строки в одну это использовать буфер вывода (ob_start()) и печатать echo в буфер. В конце получить данные функцией ob_get_contents. Это работает, потомучто для буферизации выделяется первоначальный буфер в 40 кб, который растет кусками по 10 кб.
    13. Работая с массивами и объектами используйте ссылки где это возможно. Если это короткий скрипт, и обслуживание кода это не проблема, вы можете использовать глобальные переменные для сохранения объектов и массивов.
    14. Если у вас много скриптов, использующих переменные сессии, рассмотрите возможность скомпилировать PHP для использования общедоступной памяти для сессий, или используйте RAM диск для их хранения. Включите эти возможности configure with-mm, затем перекомпилируйте PHP, а также установите session.save handler = mm в php.ini.
    15. Для поиска подстроки, используйте самую быструю команду strpos(), preg_match() и уж затем ereg(). Точно также str_replace() быстрее чем preg_replace(), которая, в свою очередь, быстрее, чем ereg_replace().
    16. Располагайте наиболее часто встречающиеся утверждения switch в самом верху. Если большинство случаев попадает под значение по умолчанию, определите его также в самом начале.
    17. Обработка XML данных регулярными выражениями работает значительно быстрее, чем использование SAX и DOM.
    18. Делайте unset() неиспользуемых более переменных, чтобы освободить память. Это главным образом полезно для ресурсов и больших массивов.
    19. Для классов с глубокой иерархией расширенные функции работают быстрее, чем определенные в основном классе (родительском). Рассмотрите возможность копирования часто используемых функций из основного класса в наследующий.
    20. Рассмотрите возможность написание вашего кода как расширение PHP или Java класс или COM объект, если вы нуждаетесь в сверхскорости. Будте осторожны при обмене данными между COM и Java.

    Бесполезная оптимизация

    Некоторые виды оптимизации полезны. Другие напрасная трата времени. Часто полезность усовершенствования пренебрежимо мала. Часто, внутренние изменения в PHP делают щипковые изменения кода устаревшими.

    Вот некоторые общие легенды:

    1. Echo быстрее чем print. Считается, что echo быстрее, так как не возвращает никакого значения, тогда как print возвращает. Из моих тестов производительности PHP 4.3 видно, что различие в них пренебрежительно малы. И в некоторых ситуациях print быстрее echo (когда ob_start включен).
    2. Удаление из кода комментариев ускоряет его выполнение. Если вы используете кэширование опкода, комментарии уже проигнорированы. Это миф, тянущийся со времен PHP 3, когда каждая строка скрипта интерпретировалась в момент ее выполнения.
    3. ‘var=’ . $var быстрее чем «var=$var». Это было справедливо для PHP 4.2 и более ранних версий. В PHP 4.3 это было устранено. Добавление от 22 июня 2004: очевидно, что в PHP 4.3 скорость была значительно увеличена, но различия устранены не полностью. Однако, я нахожу, что различия стали незначительными.

    Ускоряют ли ссылки ваш код?

    Ссылки не обеспечивают никакого преимущества для работы со строками, целыми числами и другими базовыми типами данных. Например, рассмотрим следующий код:

    И тот же самый код без ссылок:

    PHP фактически не создает копии переменных, когда обрабатывает значение, но использует вместо этого очень быструю ссылку, рассчитывая все внутри себя. Так в TestRef(), $b и $c будут устанавливаться дольше, так как ссылки должны отслеживаться, в то время как TestNoRef() $b и $c только указывают на первоначальное значение $a и PHP всего лишь увеличивает число ссылок. Поэтому TestNoRef() будет выполнена быстрее, чем TestRef().

    Напротив, функции, которые принимают массивы и объекты в качестве параметров, имеют преимущества в работе, если использовать ссылки. Это происходит потому, что массивы и объекты не используют счетчик ссылок. Поэтому при использовании массивов и объектов без ссылок будет создано множество копий, когда они будут обрабатываться. Так следующий код:

    быстрее, чем этот:

    Замечание: в PHP 5 все объекты передаются по ссылке автоматически, без требования явного указания &. Объектная модель PHP 5 должна быть значительно быстрее.

    Ускорение PHP

    Основные способы увеличения производительности (применимо при разработке или оптимизации законченных проектов):

    • Минимизация использования регулярных выражений, которые выполняются долго. Вместо regexp можно использовать функции для обработки строк: join, explode и др.
    • Отказ от объектно-ориентированного программирования там, где это возможно
    • Использование абсолютных путей в коде: include /var/site/css/style.css; вместо относительных include ../style.css; С абсолютными путями код будет выполняться быстрее
    • Одинарные кавычки для строк — известно, что переменные в строках распознаются только при использовании двойных кавычек. От этого overhead-а можно избавиться, получив увеличение производительности
    • Современные версии PHP. Код, написанный на 7.0+ работает на 20-30% быстрее, чем код на PHP 5.4 и 5.6
    • Хранение сессий в Memcached — хранение в файлах не подходит для нагруженных проектов. Чаще всего применяется Memcached. С PHP хранилище может работать за счет расширений memcache и memcached
    • Подходящие значения параметров memory_limit, max_execution_time и post_max_size в файле php.ini
    • Акселераторы PHP вроде opCache и APCu
    • FastCGI или PHP-FPM в качестве менеджера процессов, с FPM и Nginx получается самая высокая производительность
    • Постоянное профилирование кода и анализ узких мест с последующей переработкой

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

    оптимизация кода, снижение нагрузки на сервер

    Сделал сайт на самописном движке. Сталкнулся с проблемой загрузка цпу у хостера. Собственно хостер предоставляет 10% цпу, а при посещаемости 1,500 юзеров в день цпу грузится на 2,5%. Хостер предупредил сразу: если лимит цпу превысит допустимый объем, сайт блокируется мгновенно без предупреждения. Дело в том, что наш проект понравился 1 телеканалу и нас хотят грубо говоря пропиарят. Вот боимся, что хостер на нас сильно обидеться. На VPS хостинг денег пока нет. Но это только пока. В общем наша задачу удержать, на имеющемся хостинге сайт с большой посещаемостью.

    От сюда вопрос, как оптимизировать код и снизить нагрузку на сервер?

    MemCacheSize
    MaxCachedFileSize
    ObjectCacheTTL
    MaxPoolThreads
    ListenBackLog 20.09.2010, 15:39

    Как проверить степень нагрузки кода на сервер php?
    Собственно, хочу узнать, чтобы проверить оптимальна ли моя цмс. Не слишком ли нагружена. И еще.

    Распределение нагрузки на сервер
    Есть код, оптимизация которого уже в принципе невозможна. Код осуществляет простейший выбор из.

    Работа скрипта — уменьшение нагрузки на сервер
    ситуация: есть скрипт который проверяет список ссылок, посылает запрос, получает код ответа, ссылок.

    Снижение нагрузки на сервер сайта за счёт использования ajax
    Возможно ли это ? Или ajax — обычное украшательство? И как именно может это снижать нагрузку?

    Оптимизация нагрузки на сервер
    Пусть у нас система генерирует запросы на исполнение чего-то (документы). Как лучше исполнять эти.

    20.09.2010, 15:47 2

    Оптимизация бывает, грубо говоря, двух типов: оптимизировать код, и оптимизировать логику.
    Например, код, который 1000 раз вычисляет одно и то же, надо оптимизировать по логике. А код, который открыл и забыл закрыть 40 файлов, 20 результатов из БД и т.п. надо оптимизировать по коду.

    Одним словом: руками.

    20.09.2010, 15:50 3

    Решение

    1. Если метод может быть статическим, объявляйте его статическим.
    2. echo быстрее, чем print.
    3. Передавайте в echo несколько параметров, вместо того, чтобы использовать конкатенацию строк.
    4. Устанавливайте максимальное количество проходов ваших циклов for до цикла, а не во время его выполнения.
    5. Удаляйте свои переменные для освобождения памяти, тем более, если это большие массивы.
    6. Остерегайтесь магических методов, таких как __set, __get, __autoload.
    7. require_once дорого обходится.
    8. Указывайте полные пути в конструкциях include/require, меньше времени будет тратится на поиск файла.
    9. Если вам необходимо определить время, когда скрипт был запущен, используйте $_SERVER[’REQUEST_TIME’] вместо time().
    10. Старайтесь использовать strncasecmp, strpbrk и stripos вместо регулярных выражений.
  • str_replace быстрее, чем preg_replace, но strtr быстрее, чем str_replace.
  • Если функция, как и функции замены строк, может принимать в аргументы как массивы, так и одиночные символы, и если ваш список аргументов не слишком длинный, подумайте над тем, чтобы записать несколько одинаковых выражений замены, проходя один символ за раз, вместо одной строки кода, которая принимает массив как аргумент поиска и замены
  • Лучше выбирать утверждения при помощи конструкции else if, чем использовать несколько конструкций if.
  • Подавление ошибок при использовании @ работает очень медленно.
  • Используйте модуль Apache mod_deflate.
  • Закрывайте свои соединения с БД, когда закончите работать с ними.
  • $row[‘id’] в семь раз быстрее, чем $row[id].
  • Сообщения об ошибках дорого стоят
  • Не используйте функции внутри условия цикла for, например как здесь: for ($x=0; $x prop++) в три раза медленнее, чем локальной переменной.
  • Инкремент неопределённой переменной в 9-10 раз медленнее, чем заранее инициализированной.
  • Объявление глобальной переменной, без использования её в функции, также замедляет работу (примерно на ту же величину, что и инкремент локальной переменной). Вероятно, PHP осуществляет проверку на существование переменной.
  • Скорость вызов метода, судя по всему, не зависит от количества методов, определённых в классе. Я добавил 10 методов в тестовый класс (до и после тестового метода), без изменения производительности.
  • Методы в производных классах работают быстрее, чем они же, определённые в базовом классе.
  • Вызов функции с одним параметром и пустым телом функции в среднем равняется 7-8 инкрементам локальной переменной ($localvar++). Вызов похожего метода, разумеется, около 15 инкрементов.
  • Ваши строки, определённые при помощи ‘, а не «, будут интерпретироваться чуть быстрее, т.к. PHP ищет переменные внутри «..», но не ‘. ‘. Конечно, вы можете использовать это только тогда, когда в вашей строке нет переменных.
  • Строки, разделённые запятыми, выводятся быстрее, чем строки, разделённые точкой. Примечание: это работает только с функцией echo, которая может принимать несколько строк в качестве аргументов.
  • PHP-скрипты будут обрабатываться, как минимум, в 2-10 раз медленнее, чем статические HTML-страницы. Попробуйте использовать больше статических HTML-страниц и меньше скриптов.
  • Ваши PHP-скрипты перекомпилируются каждый раз, если скрипты не кэшируются. Кэширование скриптов обычно увеличивает производительность на 25-100% за счёт удаления времени на компиляцию.
  • Кэшируйте, насколько это возможно. Используйте memcached — это высокопроизводительная система кэширования объектов в памяти, которая повышает скорость динамических веб-приложений за счёт облегчения загрузки БД. Кэшированный микрокод полезен тем, что позволяет вашему скрипту не компилироваться снова для каждого запроса.
  • При работе со строками, когда вам понадобится убедиться в том, что строка определённой длины, вы, разумеется, захотите использовать функцию strlen(). Эта функция работает очень быстро, ведь она не выполняет каких-либо вычислений, а лишь возвращает уже известную длину строки, доступную в zval-структуре (внутренняя структура C, используемая при работе с переменными в PHP). Однако потому, что strlen() — функция, она будет работать медленно за счёт вызова некоторых операций, таких как приведение строки в нижний регистр и поиска в хэш-таблице, только после которых будут выполнены основные действия функции. В некоторых случаях вы сможете ускорить свой код за счёт использования хитрости с isset().
    Было: if (strlen($foo) Добавлено через 2 минуты
    и вот

    Оптимизация PHP-кода

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

    Правило №1: Старайтесь не использовать длинные переменные

    Действительно, если длина имени переменной больше 4-х символов, то скорость выполнения начинает падать. Особенно это заметно при длине от 8-ми символов.

    Правило №2: Старайтесь не использовать цикл foreach

    Цикл foreach используйте только для перебора ассоциативных массивов, а для всех остальных случаев жизни используйте только for или while. Выигрыш в скорости 25-30%.

    Правило №3: Старайтесь переменные выносить за пределы кавычек

    Давайте разберём такой код:

    Если проверить скорость выполнения, то можно заметить, что присвоение $y идёт примерно на 20% медленее, чем присвоение переменной $z. Особенно это актуально, если вместо переменной $x поставить элемент двумерного массива.

    Это были 3 правила по оптимизации PHP-кода. Если я буду обнаруживать ещё какие-то интересные моменты, то обязательно напишу 2-ю часть этой статьи. Было бы очень здорово, если бы Вы в комментариях написали ещё какие-нибудь способы оптимизировать PHP-код.

    Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

    Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
    Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

    Если Вы не хотите пропустить новые материалы на сайте,
    то Вы можете подписаться на обновления: Подписаться на обновления

    Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

    Порекомендуйте эту статью друзьям:

    Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

    Она выглядит вот так:

  • BB-код ссылки для форумов (например, можете поставить её в подписи):
  • Комментарии ( 4 ):

    Интерпретатор быстрее обрабатывает одиночные кавычки (поскольку передаваемый текст не изменяется) чем двойные. Пример: $v=7; echo ‘Саше исполнилось ‘ . $v . ‘лет’; быстрее чем echo «Саше исполнилось $v лет»;

    Касательно правила №1 по поводу длины имени переменных. Дело в том, что короткие имена крайне затрудняют в дальнейшем как понимание так и исправление возможных ошибок. И имеет смысл вначале делать все-таки максимально понятные имена, а когда надобность в отладке программы отпадет заменить их на более короткие для ускорения кода.

    Неплохо было бы еще услышать пару советов, как оптимизировать запросы к базе данных. )

    Да, неплохая тема для статьи, обязательно освещу. Спасибо!

    Для добавления комментариев надо войти в систему.
    Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.

    Copyright © 2010-2020 Русаков Михаил Юрьевич. Все права защищены.

    Спортивные секции и клубы
    в Санкт-Петербурге

    Новости спортивных секций

    Завершение строительства многофункционального спортивного комплекса для лиц с ограниченными возможностями в Приморском районе оценивается в 1 млрд 551 млн рублей.

    19 сентября 2015 года в «TAURAS-FITNESS», одном из самых больших и современных физкультурно-оздоровительных центров Санкт-Петербурга, состоится День открытых дверей детских секционных направлений!

    5–6 сентября 2015 года в Санкт-Петербурге на территории нового конгрессно-выставочного комплекса «ЭКСПОФОРУМ» в павильоне F и прилегающей уличной территории пройдет X Общественная акция «Выбираю спорт!» – ежегодное спортивное выставочное мероприятие для детей и их родителей, молодёжи и всех тех, кто любит спорт и активный отдых.

    Крытые катки на улице Маршала Новикова и Ириновском проспекте, строящиеся с прошлой весны, сдадут на год позже — в конце 2020-го. Чиновники объявили повторный конкурс на выбору нового подрядчика взамен старого.

    В Санкт-Петербурге, в «Центре плавания» (ул. Хлопина, 10), с 25 по 27 апреля пройдет чемпионат России по синхронному плаванию.

    23-25 апреля в Центре художественной гимнастики «Жемчужина» (Петровский пр., 16) пройдут Всероссийские соревнования «Жемчужины Санкт-Петербурга».

    Турнир будет проходить ежедневно с 10 до 18 часов.

    Оптимизируем загрузку PHP-кода в 22 раза, или почему FastCGI не ускоряет PHP

    Тема данной статьи — тот факт, что применение FastCGI в PHP не ускоряет время загрузки PHP-кода по сравнению, например, с mod_php.

    Большинство традиционных языков Web-программирования (Perl, Ruby, Python и т. д.) поддерживают написание скриптов, работающих в так называемом «FastCGI-режиме». Более того, Ruby on Rails, к примеру, вообще невозможно использовать в CGI-режиме, т.к. он тратит на подключение всех своих многочисленных библиотек десятки секунд.

    Ниже я расскажу о методе, который позволяет в ряде случаев ускорить загрузку объемного PHP-кода более чем в 20 раз, не получая при этом побочных эффектов и значительных неудобств. Но вначале давайте поговорим об основах…

    Что такое FastCGI?

    FastCGI работает следующим образом: скрипт загружается в память, запускает некоторый тяжелый код инициализации (например, подключает объемистые библиотеки), а затем входит в цикл обработки входящих HTTP-запросов. Один и тот же процесс-скрипт обрабатывает несколько различных запросов один за другим, что отличается от работы в CGI-режиме, когда на каждый запрос создается отдельный процесс, «умирающий» после окончания обработки. Обычно, обработав N запросов, FastCGI-скрипт завершается, чтобы сервер перезапустил его вновь уже в «чистой песочнице».

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

    Старые скрипты, написанные с расчетом на CGI, приходится дорабатывать, чтобы они могли работать в FastCGI-окружении (касается использования FastCGI в Си, Perl и т. д.; на PHP дорабатывать не нужно, но у этого свои недостатки, см. ниже). Действительно, ведь раньше скрипт стартовал каждый раз «с чистого листа», а теперь ему приходится иметь дело с тем «мусором», который остался от предыдущего запроса. Если раньше CGI-скрипт на Perl выглядел как

    то после переделки под FastCGI он становится похож на что-то типа

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

    FastCGI имеет значительный недостаток: новый запрос начинает обрабатываться не в «чистом» окружении, а в том, которое осталось «с прошлого раза». Если в скрипте имеются утечки памяти, они постепенно накапливаются до тех пор, пока не произойдет крах. Это же касается и ресурсов, которые забыли освободить (открытые файлы, соединения с БД и т. д.). Есть и еще один недостаток: если код скрипта изменился, то приходится как-то сообщать об этом FastCGI-серверу, чтобы он «убил» все свои процессы и начал заново.

    Собственно, техника «иницилизируйся один раз, обрабатывай много запросов» работает не только в FastCGI. Любой сервер, написанный на том же самом языке, что и скрипт, под ним запущенный, использует ее неявно. Например, сервер Mongrel написан целиком на Ruby как раз для того, чтобы под ним быстро запускать Ruby On Rails. Сервер Apache Tomcat, написанный на Java, быстро выполняет Java-сервлеты, т.к. не требует их повторной инициализации. Технология mod_perl также основана на том, что Perl-код не выгружается между запросами, а остается в памяти. Конечно, все эти серверы имеют те же самые проблемы с непредсказуемостью, утечками памяти и сложностью перезапуска, что и FastCGI-приложение.

    Почему FastCGI не ускоряет PHP

    Не верьте! В действительности поддержка FastCGI в PHP имеет чисто номинальный характер. Точнее, она не дает преимуществ в том смысле, в котором ей привыкли оперировать для уменьшения времени инициализации скрипта. Конечно, вы можете запустить PHP FastCGI-сервер и даже заставить nginx или lighttpd работать с ним напрямую, однако прирост скорости на загрузку кода, который вы от этого получите, будет нулевым. Тяжелые PHP-библиотеки (например, Zend Framework) как загружались долго в mod_php- или CGI-режимах, так и будут продолжать загружаться долго в режиме FastCGI.

    Собственно, это неудивительно: ведь чтобы запустить любой PHP-скрипт в FastCGI-режиме, его не приходится дорабатывать. Ни строчки измененного кода! Когда я впервые решил поэкспериментировать с FastCGI в PHP, я потратил несколько часов времени на поиски в Интернете информации о том, как именно следует модифицировать PHP-код, чтобы оптимально запускать его в режиме FastCGI. Я проштудировал всю документацию PHP и несколько десятков форумов PHP-разработчиков, даже просмотрел исходный код PHP, но так и не нашел ни единой рекомендации. Имея прежний опыт работы с FastCGI в Perl и Си, я был несказанно удивлен. Однако все встало на свои места, когда выяснилось, что изменять код не нужно и, хотя в рамках одного FastCGI-процесса обрабатываются несколько соединений, PHP-интерпретатор каждый раз инициализируется заново (в отличие от «классического» FastCGI). Более того, похоже, большинство PHP-разработчиков, радостно использующих FastCGI+PHP, даже не подозревают о том, что оно должно работать как-то по-другому…

    eAccelerator: ускорение повторной загрузки PHP-кода

    Существует ряд инструментов, кэширующих в разделяемой оперативной памяти (shared memory) оттранслированное внутреннее представление PHP-кода. Таким образом, при повторном включении PHP-файла он уже не транслируется, а байт-код берется из кэша в памяти. Естественно, это значительно ускоряет работу.

    Одним из таких инструментов является eAccelerator. Он устанавливается в виде расширения PHP (подключается в php.ini) и требует самой минимальной настройки. Рекомендую включить в нем режим кэширования байт-кода исключительно в оперативной памяти и отключить сжатие (установить параметры eaccelerator.shm_only=1 и eaccelerator.compress=0). Также установите и настройте контрольную панель control.php, идущую в дистрибутиве eAccelerator, чтобы в реальном времени отслеживать состояние кэша. Без контрольной панели вам будет очень трудно проводить диагностику, если eAccelerator по каким-то причинам не заработает.

    Преимущество eAccelerator в том, что он работает весьма стабильно и быстро даже на больших объемах PHP-кода. У меня ни разу не возникало проблем с этим инструментом (в отличие от Zend Accelerator, к примеру).

    «Мой скрипт вместе с библиотеками занимает 5 МБ, как же быть. »

    Многие на этом месте посмеются и скажут, что не надо использовать Zend Framework и Propel, т.к. они «тормозные». Но действительность заключается в том, что тормозные вовсе даже не они… Плохую производительность имеет метод, который по умолчанию использует PHP для загрузки кода. К счастью, ситуацию нетрудно исправить.

    Чтобы не быть голословным, я приведу результаты небольшого тестирования, которое я специально провел в «чистом» окружении, не привязанном к какому-либо конкретному проекту. Тестировалась скорость подключения всех файлов Zend Framework (за исключением Zend_Search_Lucene). Предварительно из кода были вырезаны все вызовы require_once, а загрузка зависимостей поизводилась только через механизм autoload.

    Итак, всего подключались 790 PHP-файлов общим объемом 4.9 МБ. Немало, верно? Подключение осуществлялось примерно так:

    Благодаря тому, что используется autoload, вызов class_exists() заставляет PHP подключить файл соответствующего класса. (Это самый простой способ «дернуть» autoload-функцию.) Порядок подключения я выбрал таким, чтобы каждый следующий класс уже имел загруженными все свои зависимые классы на момент запуска. (Этот порядок нетрудно установить, просто печатая в браузер значение $fname в функции __autoload).

    Вот результаты тестирования с eAccelerator-ом и без на моем не очень мощном ноутбуке (Apache, mod_php):

    • Подключение всех файлов по одному, eAccelerator выключен: 911 мс.
    • Подключение всех файлов по одному, eAccelerator включен: 435 мс. Занято 15 М кэш-памяти под байт-код.

    Как видите, eAccelerator дает примерно двукратное ускорение на 790 файлах общим объемом 4.9 МБ. Слабовато. К тому же, 435 мс — явно чересчур для скрипта, который только и делает, что подключает библиотеки.

    А теперь добавим стероидов

    • Включение одного большого слитого файла, eAccelerator выключен: 458 мс.
    • Включение одного большого слитого файла, eAccelerator включен: 42 мс. Занято 31 МБ кэш-памяти под байт-код.

    Первая строчка говорит о том, что один большой файл размером 4.9 МБ и правда загружается быстрее, чем 790 маленьких: 458 мс против 911 мс (см. выше). Экономия в 2 раза.

    А вот вторая строчка заставила меня от удивления подпрыгнуть на стуле и перепроверить результат несколько раз. Надеюсь, это же произойдет и с вами. Действительно, 42 мс — это в 11 раз быстрее, чем с отключенным eAccelerator-ом! Получается, что eAccelerator еще меньше любит мелкие файлы (кстати, даже в режиме eaccelerator.check_mtime=0): экономия в 11 раз.

    Итак, мы действительно получили ускорение загрузки в 22 раза, как и было обещано в заголовке. Раньше весь Zend Framework, разбитый на файлы, подключался 911 мс, а с использованием eAccelerator и объединенем всех файлов в один — 42 мс. И это, заметьте, не на реальном сервере, а всего лишь на рядовом ноутбуке.

    Вывод: ускорение в 22 раза

    • Слияние всех файлов в один большой плюс включение eAccelerator для этого большого файла дает ускорение в 22 раза при объеме кода 4.9 МБ и числе файлов 790.
    • В случае небольшого числа файлов значительного объема eAccelerator может дать 10-кратное ускорение. Если файлов много, а суммарный объем большой, то ускорение примерно в 2 раза.
    • Расход кэш-памяти зависит от числа файлов разбиения: при фиксированном объеме чем файлов больше, тем расход меньше.

    При всем при этом eAccelerator лишен основных проблем «настоящего» FastCGI-сервера. Скрипты избавлены от утечек памяти и запускаются в гарантировано «чистом» окружении. Вам также не надо следить за изменением кода и перезапускать сервер всякий раз, когда внесены модификации в мало-мальски глубинный код системы.

    Заметьте также, что мы подключали весь Zend Framework. В реальных скриптах объем кода будет сильно меньше, т.к. обычно для работы требуется лишь незначительная часть ZF. Но даже при условии, что библиотеки занимают 4.9 МБ, мы получаем время загрузки 42 мс — вполне приемлемое для PHP-скрипта. Ведь в нагруженных проектах PHP-скрипты могут работать и несколько сотен миллисекунд (Facebook, Мой Круг и т. д.).

    Конечно, если вы планируете запускать FastCGI в PHP не из соображений производительности, а просто чтобы не «завязываться» за Apache и ограничиться связкой «nginx+PHP» или «lighttpd+PHP», ничто этому не мешает. Более того, задействовав eAccelerator для FastCGI+PHP и слив много файлов кода в один большой, вы получите то же самое ускорение, которое я описал выше. Однако не тешьте себя надеждами, что ускорение дал именно FastCGI: это не так. Применяя mod_php+eAccelerator, вы достигли бы практически такого же результата, что и FastCGI+eAccelerator.

    Пара советов напоследок

    Также рекомендую вам отказаться от явного включения файлов по require_once и переходить на autoload. Только не пытайтесь использовать для этого Zend_Loader: он очень медленный (по моим замерам, подключение ста файлов отнимет дополнительно около 50 мс). Лучше напишите собственную несложную autoload-функцию, которая будет быстро выполнять всю работу. Autoload позволит вам безопасно объединять несколько файлов библиотек в один, не думая о том, как бороться с «ручными» require_once.

    Наконец, применяйте функцию set_include_path(), чтобы код подключения библиотек выглядел вот так:

    Константы, определяющие путь к директории библиотек явным образом, — большое зло и усложнение программы. Они также косвенно противоречат стандартам кодирования Zend Framework и PEAR, которых я тоже рекомендую по возможности придерживаться.

    Итак, хотите использовать «тяжелые» библиотеки в PHP-скриптах — на здоровье! PHP — скриптовый язык, по-настоящему позволяющий это делать без оглядки на неудобства FastCGI и проблемы «встроенных» серверов.

    Советы и трюки по PHP

    Небольшое вступление
    Началом написания серии статей «Советы и трюки» послужил отчет «Tips and Tricks» Расмуса Лирдофа (Rasmus Lerdorf) с конференции PHPCon2002, которая состоялясь 24 октября 2002 года в городе Milbrae, Калифорния, США. Изначально планировалось просто перевести отчет по просьбам членов Клуба разработчиков PHP, но по мере чтения статей возникло много спорных вопросов и разногласий с автором, поэтому я постарался как можно более четко определить и разъяснить преимущества и недостатки того, или иного подхода оптимизации решений.

    Часть 1. Оптимизация
    1. Без необходимости не используйте регулярные выражения.
    В PHP кроме регулярных выражений существует большое количество функций по обработке текста, которые в некоторых случаях могут заменить их, экономя при этом ресурсы сервера.

    Неправильно: = ereg_replace ( «-» , «_» , $str ); ?>
    Правильно: = str_replace ( «-» , «_» , $str ); ?>
    Неправильно: ( «/(\..*?) $ /» , $str , $reg ); ?>
    Правильно: ( $str , strrpos ( $str ,)); ?>

    2. Используйте ссылки при обработке больших массивов данных для экономии памяти сервера.
    Работа со ссылками (references) является более приемлемой при обработке больших объемов информации, хотя и немного медленней, чем работа с копией, но использует меньший объем памяти. Поэтому Вы должны самостоятельно определить, запасы каких ресурсов на сервере более рационально использовать — процессора или памяти.

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

    Учтите, в PHP реализована функция отключения постоянных соединений, поэтому если у провайдера в конфигурации PHP установлена директива mysql.allow_persistent = Off, то соединения вызываемые функцией mysql_pconnect() будут обрабатываться как mysql_connect().

    Очень часто встречаются советы не использовать постоянные соединения с БД. Это связано в первую очередь с тем, что многопоточные веб-сервера, к которым относится и Apache, не могут разделить со своими потомками соединение с БД. Таким образом если следующий запрос приходит на другого потомка, то он создает новое постоянное соединение, что со временем приводит к появлению большого количества незакрытых соединений с БД и переполнению допустимого лимита max_connections в MySQL. Возможно два решения этой проблемы: первое описано выше заключается в запрете использования постоянных соединений, второе — использовать малое значение времени жизни постоянного соединения в директиве wait_timeout конфигурации MySQL. По умолчанию оно составляет 28800 сек. (8 часов), по истечению которых после отсутствия активности соединения будет закрыто.

    Помимо всего этого существуют еще некоторые проблемы постоянных соединений с транзакциями и блокировками таблиц. Так, если таблица блокируется запросом на транзакцию или LOCK TABLE и при этом скрипт заканчивает свое выполнение до завершения транзакции или выполнения разблокировки таблицы UNLOCK TABLE соответственно, то вторичная попытка доступа к таблице через это же постоянное соединение будет отклонена. При использовании непостоянного соединения с БД, при завершении скрипта соединение закрывается автоматически и при этом снимает блокировку со всех таблиц и завершает все транзакции. Решением этой проблемы есть регистрации функции register_shutdown_function() которая бы по завершению скрипта снимала блокировку с таблиц и завершала транзакции.

    Так что можете использовать, а можете и не использовать, все зависит от поставленных задач.

    4. Используешь MySQL? Проверь mysql_unbuffered_query()
    Небуферезированные запросы к БД MySQL применяется так же как и mysql_query(). Разница заключается в том, что вместо того, чтоб ожидать полного окончания запроса сохранить результат в клиентском API, небуферизированный запрос делает доступными результаты своего выполнения как можно скорее, минуя буферизацию в клиентском API. Таким образом Вы получаете боле быстрый доступ к данным с меньшими затратами памяти. Недостатком использования такого типа запросов является невозможность получить доступ к функции mysql_num_rows(),этои запросы медленнее на маленьких выборках SELECT, а также хотелось бы заметить то, что при выполнении любого другого запроса, все данные которые небыли выведены, будут потеряны.

    5. В поисках идеала
    Если решения выглядят для Вас комплексно, то наверняка найдется более простой и очевидный подход к решению задачи.

    Илон Маск рекомендует:  Что такое код excludeupdatergn
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL