PHP: пример класса-обертки для измерения времени выполнения методов

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

Я же для таких целей предпочитаю использовать обертки классов – один раз пишется код этой обертки, потом все классы подменяю на обертку. Если система спроектирована грамотно ( а именно – нет в коде вызовов New, все классы создаются посредством фабрики), то вставка/удаление такого профайлинга занимает считанные секунды ( необходимо просто редактировать метод создания класса) . Конечно, такое решение обладает рядом недостатков, один из самых главных – профилировать можно только внешние вызовы методов, если метод вызывается из самого класса через $this, то он перехвачен не будет.

Простейший класс-обертка для целей профилирования может выглядеть примерно так:

class Wrapper {
protected $_object;

public function __construct($object) {
$this->_object = $object;
}

public function __call($name, $args) {
$start = microtime(true);
$value = call_user_method_array($name, $this->_object,$args);
$calling_time = microtime(true) – $start;
//— тут сохраняем время вызова метода, куда душа пожелает
}
}

Теперь надо модифицировать функцию создания классов, допустим вот так

class Factory {
public static function CreateClass($name) {
return new Wrapper(new $name);
}
}

Если все объекты создаются посредством данной функции, то вместо них будут созданы обертки, с таким же поведением ( тут перепределяются только вызовы функций, доступ к паблик свойствам нет. Хотя реализовать этот функционал не сложно, придется написать обертке еще 2 магических метода __set и __get ).

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



Digital Ocean
Провайдер облачного хостинга - заведи свой виртуальный сервер всего за $5 в месяц !

4 Comments

  1. Лёха zloy и красивый

    Не пользуй call_user_method_array(), ибо она может отвалится. В доках, по крайней мере, советуют использовать call_user_func_array() с первым аргументом массивом: array(обьект, ‘метод’)

Leave a Reply