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 ).
Конечно, приведенный мной подход не решит всех проблем и для более серьезного исследования поведения системы придется использовать полноценный профайлер. Но некоторым данное решение будет достаточным.
July 30th, 2008 at 6:53 am
Не пользуй call_user_method_array(), ибо она может отвалится. В доках, по крайней мере, советуют использовать call_user_func_array() с первым аргументом массивом: array(обьект, ‘метод’)