PHP: Выявляем узкие места в производительности сайта
Лирика
Каждый разработчик сайта рано или поздно сталкивается с проблемой оптимизации производительности своего проекта. Не важно по каким причинам (бурный рост, или же просто кривой код), и не важно на каком этапе (проектирование, продакшн) — нужно уметь выявлять узкие места и исправлять ситуацию. Что делать: добавлять кэш-сервера, разделять базу, оптимизировать запросы, править код и логику приложения? Решать Вам, но косвенно указать на узкое место поможет одно небольшое решение. Это обычный php-класс, который позволяет оценивать производительность любых фрагментов кода (по времени выполнения) и группировать полученные результаты. Решение с одной стороны простое до безобразия и его очень легко интегрировать в любой проект, с другой стороны может оказаться очень полезным инструментом при выявлении узких мест.Физика
Итак, вот сам класс:
<?php
/**
* Class pageSpeed
*
* @version 0.1
* @author Andrew Musinzya <a.musinzya@gmail.com>
* @copyright © Andy2
* @license <a href="http://opensource.org/licenses/gpl-license.php">opensource.org/licenses/gpl-license.php</a> GNU Public License
*
*/
class pageSpeed
{
private $startTime = 0; // global php script execution time start
private $stopTime = 0; // global php script execution time end
private $execTime = 0;
private $tmpTimerStart = 0; // temporary timer used for local benchmarks such as sql queries, cache queries etc
private $tmpTimerStop = 0;
private $tmpTimer = 0;
private $tmpStarted = false;
private $curGroup = "";
private $curGroupDesc = "";
private $execStats = array(); // all benchmark statistics collected here
public $statistics = "\n\n\n";
}
}
?>
Теперь о том, как его использовать. Ближе к началу кода создаём объект:
$obj = new pageSpeed();
в самом конце кода вызваем метод finish:
$obj->finish();
После чего вся статистика доступна в свойстве statistics (в виде закоментированной html-строки).
echo $obj->statistics;
Теперь самое главное: нам нужно оценивать производительность интересуемых фрагментов кода. Для этого, вначале нужного фрагмента вызываем метод:
$obj->benchStart("Имя группы", "Описание действия");
и в конце фрагмента:
$obj->benchStop();
На этом все! Больше ничего не потребуется.
В качестве имени группы (метода benchStart) стоит выбрать имя некой логической темы, к которой относится исследуемый участок кода. Например, измеряя скорость выполнения SQL-запроса к БД в качестве имени группы можно использовать «SQL» или «SQL QUERIES», для запросов к кэшу — «MEMCACHE», к файловой системе — «FILES» и т.д. Важно понимать, для всех однородных операций лучше указывать одну и ту же группу. Таким образом можно будет определить производительность не только отдельной операции, но и всей подсистемы в целом.
В качестве описания действия можно указать любую строку, описывающую выполняемую операцию. Например «Executing SQL query 1», «Get user session data» или же сам SQL-запрос. Возможно, сейчас все выглядит запутанным и непонятным, но, думаю, следующий пример поставит все на свои места:
<?php
include 'serverside/core.speed.php'; // это наш класс
$obj = new pageSpeed();
// ------------------
$obj->benchStart("SQL QUERIES", "Getting user list");
echo "SELECT * FROM ...";
$obj->benchStop();
// ------------------
$obj->benchStart("SOME SHIT", "Put aaa into web universe");
echo "aaa" . "
";
sleep(1);
$obj->benchStop();
// ------------------
$obj->benchStart("SQL QUERIES", "Store session data");
for ($i=2;$i<20;$i++)
{
for ($j=1;$j<1745;$j++)
{
for ($k=1;$k<851;$k++)
{
$x = true;
}
}
}
$obj->benchStop();
// ------------------
$obj->benchStart("SQL QUERIES", "Get friends");
for ($i=2;$i<400;$i++)
{
$y = "Friends will be friends.";
}
$obj->benchStop();
// ------------------
$obj->finish();
echo $obj->statistics;
?>
В результате, в конце сгенерированного html будем иметь следующую статистику:
Единственное ограничение — не поддерживаются вложенные вызовы. Будьте внимательны.
Вот в принципе и все, чем хотел поделиться. Спасибо за внимание. Надеюсь, кому-нибудь да пригодится.
0 комментариев