Ускорение PHP-программ. Ускорение PHP-программ Оптимизация клиентской стороны на php

В наши дни, когда выделенный канал Интернета стал нормой, не особо стоит переживать о размере страничек. Однако, все таки на это стоит обращать внимание. Если Вы хотите уменьшить нагрузку на сервер, сократить количество HTTP запросов - для этого существует несколько техник. Этот урок расскажет о нескольких PHP трюках (кеширования, сжатие).

1. Объединение CSS файлов с помощью PHP .

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

Подготовка

Перед оптимизацией CSS файлов, нам необходимы стили для работы. Давайте создадим несколько файлов с стилями:

// main.css
// CSS для примера

body {
width: 800px;
margin: 0 auto;
color: grey;
}

#wrapper {
margin-top: 30px;
background: url(../images/cats.png);
}
// typography.css
// CSS для примера

body {
font-family: Arial, san-serif;
font-weight: bold;
}

strong {
font-size: 120%;
}
// forms.css
// CSS для примера

form {
position: relative;
top: 400px;
z-index: 99;
}

input {
height: 50px;
width: 400px;
}

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

//Определяем переменные
$cssPath = "./css/";
if (isset($_GET["q"])) {
$files = $_GET["q"];
// Получаем массив файлов


foreach ($files as $key => $file) {
}

$cssData = "";
foreach ($files as $file) {

fclose($fileHandle);
}
}
// Скажи браузеру, что у нас CSS файл
if (isset($cssData)) {
echo $cssData;
} else {
}
?>

//Определяем переменные
// --- NOTE: PATHS NEED TRAILING SLASH ---
$cssPath = "./css/";
if (isset($_GET["q"])) {
$files = $_GET["q"];
// Got the array of files!

//Давайте убедимся, что в файловых именах нет страшных символов:) .
foreach ($files as $key => $file) {
$files[$key] = str_replace(array("/", "\\", "."), "", $file);
}

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

$cssData = "";
foreach ($files as $file) {
$cssFileName = $cssPath . $file . ".css";
$fileHandle = fopen($cssFileName, "r");

$cssData .= "\n" . fread($fileHandle, filesize($cssFileName));
fclose($fileHandle);
}
}

Теперь нам необходимо создать общую таблицу стилей из файлов. Для этого мы запускаем цикл, который просматривает массив файлов, открывает каждый файл и соединяет в единый файл. "\n" добавляет новую строку для порядка и чистоты. Функция filesize() используется для того, чтобы узнать длину файла и передать fread().

// Скажи браузеру, что у нас CSS файл
header("Content-type: text/css");
if (isset($cssData)) {
echo $cssData;
echo "\n\n// Generated: " . date("r");
} else {
echo "// Files not avalable or no files specified.";
}
?>

Последняя часть кода передает все стили браузеру. Это значит, что нам необходимо сказать PHP, что мы передаем CSS информацию и что PHP должно проинформировать об этом браузер. Мы делаем это с помощью функции header(), и устанавливаем Content-type: text/css. Далее мы передаем CSS клиенту. Но перед этим проверяем наличие CSS стилей в файле. Если их нет, значит это означает, что названия CSS файлов не были переданы. Если же у нас есть файлы мы их передаем и добавляем сообщение о генерации.

Проверка

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

Теперь загрузите все файлы в корень сайта и обратитесь к файлу index.php через браузер. Вас должна встретить фраза "Files not available or no files specified" (файлы не доступны или не указаны). Это означет, что мы не дали названия файлов, которые необходимо соединить. Однако, хорошая новость - что все работает без ошибок. Давайте попробуем напечатать в браузере "index.php?q=main". У Вас на экране появится содержание файла main.css. Если нам необходимо извлечь несколько файлов и объединить их, нам необходимо отправить следющий запрос "index.php?q=main&q=forms". Как Вы видите мы можем повторять "q=" сколько угодно раз. Вы можете объединить в один файл хоть 50 таблиц стилей.

Заключение

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

Небольшое предупреждение: если Вы поместите файл index.php в любую папку (не в папку с CSS), тогда Вам необходимо прописывать относительные пути к фоновым изображениям так, как будто index.php является Вашей таблицей стилей. Так будет думать браузер.

2. Удаление пустых строк из HTML и CSS

Многие из нас используют большое количество пустых строк при написании кода. Хорошие новости - пустые строки в PHP не передаются браузеру. Однако, передаются в HTML.

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

Подготовка

Ниже представлены коды для HTML и CSS файлов.

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


Hey a Page!






Lorem Ipsum dol...



body {
min-height: 800px;
background: black;
font-size: 18px;
}
#wrapper {
width: 960px;
margin: 20px auto;
padding: 15px;
}
#header h1 {
text-indent: -99999em;
background: url(../images/header.png);

Display: block;
width: 100%;
height: 48px;
}
#mainbody {
font-weight: bold;
}

Преимуществом данного скрипта является то, что он может одновременно работать как с HTML, так и с CSS. Скрипт загружает файл, убирает все пустые строки, оставляет только 1 пробел, чтобы слова не соединялись в одно целое.

$fileDirectory = "";
$file = $_GET["q"];
$ext = $nameExplode;

//Проверка для хакеров
die("Hackers...!");
} else {
//Начнем


//Чудеса регулярных выражений

fclose($handle);
//Выводим данные
if ($ext == "css") {
header("Content-type: text/css");
}
echo $newData;
}
?>

Более подробно о каждой части кода

Мы получаем имя файла и проверяем его тип. Далее извлекаем все данные и убираем пробелы и пустые строки. Этот метод наиболее примитивный и не удалит все пустые строки, но он справится с большинством. И это всего несколько строк кода.

$fileDirectory = "";
$file = $_GET["q"];
$nameExplode = explode(".", $file);
$ext = $nameExplode;
$fileName = $fileDirectory . $file;

Этот код задает необходимые переменные. Снова, мы передаем все данные через "q". Тут также определяется папка для файлов.

If ($ext != "css" AND $ext != "htm" AND $ext != "html") {
//Проверка для хакеров
die("Hackers...!");
} else {

Тут мы проверяем действительно ли файл является CSS или HTML.

//Начнем
$handle = fopen($fileName, "r");
$fileData = fread($handle, filesize($fileName));
//Чудеса регулярных выражений
$newData = preg_replace("/\s+/", " ", $fileData);
fclose($handle);
//Выводим данные
if ($ext == "css") {

header("Content-type: text/css");
}
echo $newData;
}
?>

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

Работает ли это?

Если Вы в браузере напечатаете "index.php?q=css.css", то увидите одну линию CSS. Значит все работает! Если откроете исходный код страницы, то увидите такую же картину. С помощью данного метода мы уменьшили 314 символьный CSS файл до 277 символов. HTML файл с 528 до 448 символов. Неплохо для 15 строк кода.

Заключение

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

3. Кеширование PHP скриптов.

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

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

Подробнее

$fileDirectory = "";
$file = $_GET["q"];
$nameExplode = explode(".", $file);
$ext = $nameExplode;
$fileName = $fileDirectory . $file;
//-- WE HAVE ENOUGH DATA TO GENERATE A CACHE FILE NAME HERE --
if ($ext != "css" AND $ext != "htm" AND $ext != "html") {
//Check for evil people...
die("Hackers...!");
} else {

//-- WE CAN INTERCEPT AND CHECH FOR THE CACHED VERSION HERE --

//Lets get down to business
$handle = fopen($fileName, "r");
$fileData = fread($handle, filesize($fileName));
//Now for some regex wizardry!
$newData = preg_replace("/\s+/", " ", $fileData);

Fclose($handle);
//Time to output the data.

//-- NOW WE CAN STORE THE NEW DATA IF REQUIRED AND OUTPUT THE DATA --

If ($ext == "css") {
header("Content-type: text/css");
}
echo $newData;
}
?>

$fileDirectory = "";
$file = $_GET["q"];
$nameExplode = explode(".", $file);
$ext = $nameExplode;
$fileName = $fileDirectory . $file;
$cacheName = "./cache/" . $nameExplode . $nameExplode . ".tmp";
if ($ext != "css" AND $ext != "htm" AND $ext != "html") {
//Хакеры
print_r($ext);
die("Hackers...!");
} else {
if (file_exists($cacheName) AND filemtime($cacheName) > (time() - 86400)) {


fclose($cacheHandle);
$isCached = TRUE;
} else {
//Начнем
$handle = fopen($fileName, "r");
$fileData = fread($handle, filesize($fileName));
//Чудеса регулярных выражений
$newData = preg_replace("/\s+/", " ", $fileData);
fclose($handle);
//Кешируем


fclose($cacheHandle);
$isCached = FALSE;
}
//Выводим данные
if ($ext == "css") {
header("Content-type: text/css");
if ($isCached) {

}
} else {
if ($isCached) {
echo "";

}
}
echo $newData;

Объяснение

В данном скрипте была добавлена функция обновления кеша каждые 24 часа. Это удобно. Допустим, если Вы поменяли что-либо на сайте - можете подождать 24 часа или же очистить кеш.

$cacheName = "./cache/" . $nameExplode . $nameExplode . ".tmp";

Этот отрезок кода достает название файлов и их расширения, склеивает их вместе и добавляет в кеш с правильным расширением ".tmp".

If (file_exists($cacheName) AND filemtime($cacheName) > (time() - 86400)) {
$cacheHandle = fopen($cacheName, "r");
$newData = fread($cacheHandle, filesize($cacheName));
fclose($cacheHandle);
$isCached = TRUE;
} else {

Тут мы проверяем наличие сохраненного кеша и был ли он создан в течении последних 24 часов (значение в секундах - можно поменять на любое другое). Если оба условия выполняются, открываем файл и извлекаем содержание, чтобы заменить им результат работы скрипта. Мы также устанавливаем $isCached true для вывода дополнительных сообщений в конце.

//Lets cache!
$cacheHandle = fopen($cacheName, "w+");
fwrite($cacheHandle, $newData);
fclose($cacheHandle);
$isCache = FALSE;
}

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

//Time to output the data.
if ($ext == "css") {
header("Content-type: text/css");
if ($isCached) {
echo "// Retrieved from cache file. \n";
}
} else {
if ($isCached) {
echo "";
}
}

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

Пробуем

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

Заключение

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

Подводим Итоги

В данном уроке я Вам показал несколько удобных и простых путей ускорения Вашего сайта с помощью PHP.

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

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

Приведу простейший пример, пусть на сервере, имеющем 100 Мб свободной оперативной памяти, находятся два скрипта, результат работы которых одинаков. Первый скрипт оптимизирован на максимальное быстродействие, требует 10 Мб памяти и получает данные из файла путем полного его прочтения, второй - на минимальный расход памяти, требует 5 Мб памяти и получает данные из того же файла по частям. В результате одного запроса, первый скрипт выполнится быстрее второго, но если будет более десяти запросов одновременно, именно скорость работы второго скрипта станет более высокой. Почему же так происходит? В первом скрипте узким местом является использование ресурсов памяти, во втором - особенности системы ввода-вывода. После расхода первым скриптом всей доступной оперативной памяти, система перейдет к использованию виртуальной памяти, при этом, дополнительным узким местом этой схемы станет та же система ввода-вывода.

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

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

Ниже перечислены основные действия по повышению производительности для PHP 5 версии:

Действия по оптимизации расхода оперативной памяти:

  1. Анализ результатов работы ваших функций. Перед написанием функции проверьте, не существует ли стандартный аналог.
  2. Освобождение памяти в случае окончания использования больших массивов или объектов только в глобальной области видимости (в локальной области видимости память будет освобождена автоматически). Обратите внимание, что функция unset() удаляет переменную из области видимости и, только в случае отсутствия на объект других ссылок, освобождает занимаемую объектом память. Присвоение переменной значения null всегда уничтожает объект и освобождает занимаемую объектом память, независимо от того, имеются ли ещё ссылки на этот объект. При этом переменная не будет удалена из области видимости, т.е. фактически переменная будет содержать неопределенное (нулевое) значение и, соответственно, занимать память на содержание этой переменной (порядка 72 байт).
  3. Анализ оправданности использования ООП (объектно-ориентированного программирования). Перед написанием объектно-ориентированного кода, задайте себе два вопроса: «нужен ли здесь объектно-ориентированный подход?» и «могу ли я писать объектно-ориентированный код?». Например, определение статической функции внутри класса увеличивает объем памяти, необходимой только для содержания этой функции, на 10-18%. Использование в качестве структуры массива, а не класса, также позволяет сэкономить память. Возможно, будет выгоднее просто вынести функции в отдельный файл, а не реализовывать их в качестве методов класса.
  4. Анализ возможности реализации статической версии метода в классе. Если метод не использует параметр $this , то он должен быть объявлен с использованием ключевого слова static .

Действия по увеличению скорости исполнения кода:

  1. Анализ оптимизированности SQL-запросов. В большинстве проектов именно оптимизация SQL-запросов дает наибольшее увеличение производительности.
  2. Использование буферизации вывода, всевозможных кеширующих модулей, позволяет увеличить производительность на 25%-100%.
  3. Использование более коротких коротких имен для переменных, функций, констант и классов может повысить производительность до 20%. В то же время не забывайте о дальнейшей поддержке кода, говорящее имя функции намного удобнее при модификациях кода.
  4. Проверка существования переменной (функция isset() ) перед обращением к ней. Подавление ошибки, возникающей при обращении к несуществующей переменной, путем использования @ сильно снижает производительность.
  5. Использование "одинарных кавычек" позволяет интерпретировать код быстрее, т.к. в случае "двойных кавычек" внутри строки ведется поиск переменных
  6. Анализ возможности выноса «лишних» функций из цикла. Например, замена функции count() на переменную, вычисленную до начала цикла и содержащую результат этой функций, в выражении for($i=0; $i повысит производительность этого цикла. В противном случае функция count() будет вызываться и выполняться на каждой итерации цикла.
  7. Использование оператора case вместо множественного использования конструкции if...else .
  8. Использование явного обращения к полям массива. Обращение вида $array["id"] выполняется в 7 раз быстрее, чем обращение $array . Кроме того, это защищает от ошибок при дальнейшей поддержке скрипта, т.к. в один прекрасный день может появиться константа с именем id .
  9. Использование дополнительной переменной, содержащей ссылку на конечный массив, при обработке многомерных массивов в цикле. Для ускорения цикла for($i = 0; $i < 5; $i++) $a["b"]["c"][$i] = func($i); , до начала цикла возможно записать следующую инструкцию $item =p$a["b"]["c"] и переписать цикл так: for($i = 0; $i < 5; $i++) $ref[$i] = $i; .
  10. Использование модулей Apache mod_gzip и mod_deflate позволяет сократить трафик, за счет чего увеличится скорость загрузки страниц.

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

  1. Использование ++$i вместо $i++ в циклах дает прирост производительности в 6%.
  2. Использование "двойных кавычек" для конкатенации (склеивания) переменных. Инструкция вида $s="$s1$s2$s3" интерпретируется быстрее, чем $s=$s1.$s2.$s3 . Это утверждение справедливо только для трех и более переменных.
  3. Использование полных путей в инструкциях include и require позволит тратить меньшее время на поиск системой реального пути.
  4. Закрытие открытых коннектов к базе данных после того как необходимость в них отпадает. В то же время не следует много раз подключаться к одной и той же базе данных.
  5. Анализ возможности замены include() и include_once() на require() и require_once() соответственно.
  6. Использование HTML-вставок в код, вместо вывода значительного объема oстатическихo строк (не содержащих результатов работы кода). Вообще, скорость выдачи статической страницы (HTML), в несколько раз быстрее выдачи страницы написанной на PHP. Но здесь не стоит увлекаться, т.к. ввод в интерпретатора в режим обработки PHP и вывод из него также нагружают сервер.
  7. Анализ возможности замены функций preg_replace и str_replace в некоторых случаях. Функция str_replace работает быстрее, чем preg_replace , и в тоже время функция strtr быстрее функции str_replace . Также, использование строковых функций strncasecmp , strpbrk и stripos более оптимально, чем использование регулярных выражений. Однако, вместо вложенности этих функций, следует использовать именно функции регулярных выражений.
  8. Использование явной инициализации переменных. Например, инкремент неинициализироанной переменной в 9-10 раз медленнее, чем предварительно инициализированной. Кроме того, при явной инициализации переменных возникает меньше ошибок.
  9. В качестве заключения хотелось бы отметить, что использование конструкции echo , вместо функции print , не дает ощутимого роста производительности.
  • Для определения времени начала исполнения скрипта, вместо функций, возвращающих текущее время, предпочтительнее использование $_SERVER["REQUEST_TIME"] .
  • Используйте профайлер для определения критических участков кода.

Перед оптимизацией быстродействия кода, я настоятельно рекомендую проверить оптимизацию SQL-запросов к базе данных, а также оптимизировать http-запросы, уменьшить размер js и css, подумать над кэшированием шаблонов, и только после этого заняться проверкой кода на производительность.

Хороший стиль программирования предполагает оптимизацию во время написания кода, а не латание дыр в последствии.


Как без особых усилий заставить PHP -код работать на порядок быстрее ? Перед тем как задаваться вопросами кеширования и масштабирования стоит попробовать оптимизировать код. Есть ряд несложных правил:

Еще про оптимизацию....

При вставке кусков PHP-кода в HTML страницы всегда используйте полные открывающие и закрывающие скобки ! Это обезопасит Вас от вариаций настройки php.ini short_open_tag на разных серверах и возможно сэкономит много времени при переносе или загрузке проектов на разные сервера.

Старайтесь использовать функцию вывода echo вместо printf и sprintf там где возможно. Нет надобности использовать эти функции, так как они выполняются медленней потому, что созданы для интерпретации и вывода строки с ее обработкой, подстановкой значений, в отформатированном виде. О чем и говорит буква f в конце названия этих 2-х функций.

Sprintf("мама"); printf("папа");

Echo "мама"; echo "папа";

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

Лучший вариант(самый быстрый)

Echo "Вес равен: ".$weight;

Худший вариант(медленный):

Echo "Вес равен: $weight";

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

$i = 0; if ($i != 0) { //Не равно } else { //Равно }

$i = 0; if ($i > 0) { //Не равно } else { //Равно } Нужно также учитывать, что если строка принимает только пустое значения, либо пользовательские строковые данные, то вместо сравнения строки со строкой, для выявления ее пустоты, так же можно использовать сравнение с нулем, которые выполнится быстрее.

Для проверки строки на пустоту используйте функцию trim($str) ; Она не только проверит заполнена ли строка, но также обрежет несущественные символы - пробелы (табуляции, white-spaces) и вернет положительное значение, в случае если в строке ей действительно какие то значимые символы.

If ($str != "") { //обработка строки }

If (trim($str)) { //обработка строки }

Для получения данных из форм методом Get и Post лучше использовать следующий минимальный набор самописных функций:

GetParam ($array, $value, $default = "") { return (isset($array[$value])) ? $array[$value] : $default; } GetParamSafe ($array, $value, $default = "") { return (isset($array[$value])) ? addslashes($array[$value]) : $default; }

Функция GetParam($_POST, "myvar", "empty") к примеру коректно получит данные из $_POST["myvar"], и в случае если $_POST переменная не существует вернет значение по умолчанию, без всяких Waring и Notice. Фунция GetParamSafe($_POST, "myvar", "empty") делает ту же операцию, только возвращает экранированную переменную. Для защиты от SQL инъекций к примеру. А данная конструкция позволяет получить целочисленное число из $_POST.

Intval(GetParam($_POST, "myvar", "empty")):

В случае если в массиве $_POST лежало совсем не число функия вернет 0;

Для простого сравнения строк не используйте preg_match() или preg_match_all() . Используйте strstr() и strpos() .

При получении строк из базы данных (MySQL к примеру) старайтесь использовать функцию mysql_fetch_object . К примеру при изменении кода запроса с

$query = "SELECT field7, field3 FROM mytable WHERE id = 5" на $query = "SELECT * FROM mytable WHERE id = 5" код вывода строки полученной из этих запросов $row = mysql_fetch_array(mysql_query($query)); echo $row."-->".$row; //перестанет работать, в то время, как $row = mysql_fetch_object(mysql_query($query)); echo $row->field7."-->".$row->field3; // останется работоспособным.

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

При формировании больших запросов вставки данных в БД через insert все строчки старайтесь поместить в один-три insert"а. Выполнение каждой строчки отдельно не только загрузит сервер БД, но и задержит работу Вашего скрипта.

В случае если необходимо в разных местах (разных классах) одной системы использовать одни и те же сложно вычисляемые данные (например которые достаются из БД через запрос с последющей обработкой строк), старайтесь их вычислять единожды, хранить глобально для всей системы и передавать в класс(скрипт) один раз, непосредственно при создании класса (подключении скрипта)

При больших нагрузках на Web-сервер задумайтесь над использованием стандартных решений для включения кэша(кэш-технологии). Например бесплатный PHP класс JCache_Lite_Function.

При проектировании/разработке больших систем отдавайте предпочтение Объектно-Ориентированному программированию с использование шаблонов проектирования. Наиболее частые шаблоны: MVC, PageController, BodyHandler, Fabric...


Читать дальше:

Одним из основных критериев успешности любого интернет-ресурса является скорость его работы и с каждым годом пользователи становятся всё более и более требовательными по этому критерию. Оптимизация работы 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; ++$i) {...} быстрее, чем for($i = 0; $i < sizeOf($array); ++$i) {...}
    Это вызвано тем, что во втором случае операция sizeOf будет выполнятся при каждой итерации. Время разницы выполнения зависит от числа элементов массива.
  • x = sizeOf($array); for($i = 0; $i < x; ++$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
    Первый вариант быстрее в 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)) {...} для ассоциативных массивов
  • Не комментированный код быстрее, чем комментированный, так как уходит дополнительное время на чтение файла
    Весьма глупо уменьшать объём комментариев ради оптимизации, надо просто в рабочих («боевых») скриптах проводить минимизацию.
  • Переменные с короткими названиями быстрее, чем переменные с длинными названиями
    Это вызвано сокращением объёмов обрабатываемого кода. Аналогично предыдущему пункту, надо просто в рабочих («боевых») скриптах проводить минимизацию.
  • Разметка кода с использованием табуляции быстрее, чем с использованием пробелов
    Аналогично предыдущему пункту.

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


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

Изучил весь httpd.conf, перекопал кучу гайдов по highload (они старые и с сомнительными советами типа "отключить лишние модули"
Один из первых модулей, который стоит отключить у Apache"а, для скорости - это поддержку файлов.htaccess, сама эта поддержка производительности не добавляет, а наличие этих файлов - уж и подавно.
1) Это у всех VPS так называемый "мощный" процессор медленнее, чем на каком-то жалком хостинге, пусть и с VIP-тарифом?
Нет, возможно это у Вас, персонально, какой-то дрянной VPS-хостер, или того хуже, тариф аки "OpenVZ, мы не перепродаём проданные ресурсы... ну разве что раз 10, но больше не перепродаём"
2) Поможет ли в такой ситуации FastCGI?
FastCGI - это режим работы PHP, напрямую, на производительность в значительной степени он не влияет, более того, сама логика работы FCGI (если сравнивать Apache-FCGI и Apache-mod_php) будет медленнее, по тому как для взаимодействия FastCGI будет использоваться сокет ("обычный" или unix-сокет), что подразумевает сетевое взаимодействие, вместо непосредственной работы интерпретатора PHP "внутри" сервера. Думаю, Вам поможет несколько другое (постараюсь описать ниже).
3) Почему не популярны фишки типа eAccelerator (кеширование AST и т.п.)?
Понятия не имею, почему они не популярны и откуда у Вас такая статистика... Но, возможно, дело в том, что eAccelerator морально и физически устарел, и если верить например, вот такой банальной статье (нет, я не работаю с такой "шедевральной" CMS как "Битрикс", просто это первое упоминание про eAccelerator, которое пришло мне в голову) - с версиями PHP выше 5.3 не работает.
Я знаю, что многие из них заброшены, но это не причина, а следствие.
Не могу прокомментировать это, так как Вы не указали следствие - чего именно. Другими словами, я не совсем понимаю, что Вы хотели этим сказать.
4) Что еще может помочь?
Ну так, сходу, по памяти (варианты могут быть не связаны между собой):
1. Отказ от поддержки.htaccess в Apache или хотя бы сокращение их количества
2. Установка Nginx в качестве фронтального сервера, для отдачи статики
3. Полный отказ от Apache вообще и переход на Nginx+FCGI (только не подумайте, я очень люблю Apache за его гибкость в настройке и широкие возможности, другой вопрос, что мало кому эта гибкость фактически нужна и мало кто способен его грамотно, качественно и полноценно настроить... Nginx в этом плане будет куда попроще). Почему FCGI? По тому, что другой приемлемый способ взаимодействия Nginx"а с PHP мне не известен. Настройка FCGI-пула - обязательна.
4. OpCache - с версии 5.5 встроено "искаропки", к включению и настройке - настоятельно рекомендуется. Я не знаю, как обстоят дела с CMS и используете ли Вы CMS на сайте, но из моей практики, скорость работы PHP-фреймворков возрастает в среднем 8-20 раз.
5. HHVM , как альтернатива
6. Проверка:
а) Того, что дело действительно в PHP. В частности, стоит собрать все логи сервера, например, сколько длились запросы, в БД, их количество и так далее.
б) Проверка скорости работы дисковой подсистемы... Не буду "тыкать пальцем", но одно время я арендовал довольно большое кол-во VPS"ок у одного популярного хостера, и в какой-то момент, я заметил, что средняя скорость работы дисковой подсистемы - 1.4Кбайт/сек., при этом "отказы" (аки "невозможно записать блок") были примерно в 50% случаев... это продлилось не очень долго, но и через несколько месяцев, у этого же хостера, тарифы с "обычным HDD", почему-то обладали более быстрой дисковой подсистемой, нежели тарифы с "быстрыми SSD"... можно сделать выводы...
в) Проверить реальную скорость работы процессора, не редко она отличается от завяленной достаточно сильно.

P.S. Если Вы сформулируете вопрос(ы) более точно - я смогу дать более точные рекомендации, если конечно они Вам нужны:)

P.P.S. Есть вариант решения проблемы вообще "в лоб", самый наверное сложный и пожалуй самый производительный в ряде случаев. Это Varnish + тонкая настройка оного, позволяет выдавать большую часть страниц из кэша (оперативной памяти) за наносекунды, иногда позволяет обслуживать очень много тысяч запросов в минуту, при этом, это не просто кэширование кода или что-то подобное... это кэширование целиком страниц и/или ответов сервера. Среди прочего - позволяет "не трогать бэкенд вообще", т.е. при запросе страницы, может не быть ни обращений к БД, ни выполнения того же PHP (или любого другого) кода, на стороне сервера. Требует довольно тонкой настройки, не очень подходит для сайтов "на CMS", для сайтов на фреймворках - требует изначально корректного подхода к разработке и продумывания того, что и как будет/должно кэшироваться. При некорректном подходе - наиболее вероятный результат - работать будет, но не так быстро как хотелось бы, а часть сайта вообще может перестать нормально функционировать. Есть так же другие решения, но с учётом довольно общих формулировок вопроса - говорить о них довольно сложно.

Ах, да, забыл важную деталь... Почему "хостинги" используют Apache и не откажутся от него (совсем)? В большей степени по тому, что Apache позволяет делегировать часть настроек пользователю через.htaccess. При этом, для статики не редко стоит всё тот же Nginx, который, как Вы понимаете, подобным образом делегировать часть настроек пользователю не позволяет, в виду чего для этих задач не подходит и не "буксует" на этом (в отличии от Apache"а). В т.ч. и по этому, мы на 99% отказались от "хостингов" (по причине наличие Apache"а, и невозможности от него избавиться или самостоятельно настроить, и как следствие "тормозов" которые приходят вместе с подобным подходом).



error: Content is protected !!