microtime para calcular esse tempo, chamando-a antes e depois do trecho de código que queremos calcular o tempo de execução, e depois subtraindo o primeiro do último.Isso é muito útil, principalmente para trabalharmos na melhora da performance do código. Foi daí que me deu a idéia de criar um plugin para Zend Framework para facilitar o uso dessa função, e eis o resultado:
class My_Controller_Plugin_ElapsedTimeUfa, parece coisa demais pra uma coisa tão simples, não é? Mas tudo isso nos dá a possibilidade de medir o tempo de execução a partir de várias partes diferentes do código, que é uma facilidade que os plugins do ZF nos oferece, então, por que não aproveitar isso pra fazer um plugin mais completo, não é?
extends Zend_Controller_Plugin_Abstract
{
/*
* Constantes que serão usadas para identificar a partir de
* que parte da execução deseja-se calcular o tempo decorrido.
* O nome das constantes é baseado no nome das funções que
* inicializam os valores correspondentes na propriedade
* $_startTime, logo abaixo
*/
const EVENT_ROUTE_STARTUP = 1;
const EVENT_ROUTE_SHUTDOWN = 2;
const EVENT_DISPATCH_LOOP_STARTUP = 3;
const EVENT_PRE_DISPATCH = 4;
const EVENT_POST_DISPATCH = 5;
const EVENT_DISPATCH_LOOP_SHUTDOWN = 6;
// Guarda o tempo de inicialização de cada parte da execução
static protected $_startTime = array(
self::EVENT_ROUTE_STARTUP => null,
self::EVENT_ROUTE_SHUTDOWN => null,
self::EVENT_DISPATCH_LOOP_STARTUP => null,
self::EVENT_PRE_DISPATCH => null,
self::EVENT_POST_DISPATCH => null,
self::EVENT_DISPATCH_LOOP_SHUTDOWN => null
);
// Define o tempo de inicialização antes de as rotas serem
// inicializadas
public function routeStartup(
Zend_Controller_Request_Abstract $request)
{
self::$_startTime[self::EVENT_ROUTE_STARTUP] =
$this->microtime();
}
// Define o tempo de inicialização depois de as rotas serem
// inicializadas
public function routeShutdown(
Zend_Controller_Request_Abstract $request)
{
self::$_startTime[self::EVENT_ROUTE_SHUTDOWN] =
$this->microtime();
}
// Define o tempo de inicialização antes de iniciar o loop
// de dispatch
public function dispatchLoopStartup(
Zend_Controller_Request_Abstract $request)
{
self::$_startTime[self::EVENT_DISPATCH_LOOP_STARTUP] =
$this->microtime();
}
// Define o tempo de inicialização antes do dispatch de
// uma action
public function preDispatch(
Zend_Controller_Request_Abstract $request)
{
self::$_startTime[self::EVENT_PRE_DISPATCH] =
$this->microtime();
}
// Define o tempo de inicialização depois do dispatch de
// uma action
public function postDispatch(
Zend_Controller_Request_Abstract $request)
{
self::$_startTime[self::EVENT_POST_DISPATCH] =
$this->microtime();
}
// Define o tempo de inicialização depois de finalizar o
// loop de dispatch
public function dispatchLoopShutdown()
{
self::$_startTime[self::EVENT_DISPATCH_LOOP_SHUTDOWN] =
$this->microtime();
}
/**
* Retorna o tempo de inicialização de cada evento do plugin,
* ou de um evento específico, que pode ser passado como
* parâmetro baseado no valor das contantes desta classe
*
* @param int $event
* @return mixed Float se receber $event, senão, array
*/
public function getStartTime($event=null)
{
if ($event) {
if (!isset(self::$_startTime[$event])) {
throw new Zend_Exception('Invalid value for $event: '
. $event);
}
return self::$_startTime[$event];
}
return self::$_startTime;
}
/**
* Calcula o tempo decorrido de um trecho e código.
*
* @param int $event
* @return float
*/
public function getElapsedTime(
$event=self::EVENT_ROUTE_STARTUP)
{
$startTime = $this->getStartTime($event);
// Lança uma excessão Caso o evento não tenha sido
// inicializado ainda
if (!$startTime) {
throw new Zend_Exception('Event has not been '
. 'initialized yet');
}
// Pega o microtime atual e substrai dele o tempo
// inicial para calcular o tempo decorrido
$endTime = $this->microtime();
$elapsedTime = $endTime - $startTime;
return $elapsedTime;
}
/**
* Pega o microtime em formato float, levando em conta as
* variações sofridas pela função de acordo com a versão do
* PHP
*/
private function _microtime()
{
if (version_compare(PHP_VERSION, '5.0.0', '>=')) {
// O parâmetro já converte o restulado da função para
// float a partir da versão 5.0.0
return microtime(true);
} else {
// Antes da versão 5.0.0, a conversão para float tinha
// que ser feita manualmente
list($usec, $sec) = explode(" ", microtime());
return ((float)$usec + (float)$sec);
}
}
}
Feito o plugin, agora vamos ao View Helper, que vai se encarregar de pegar o valor definido no plugin e subtraí-lo de um novo
microtime para exibir na página:class My_View_Helper_ElapsedTimeAgora é só chamar o view helper lá no script pra exibir o tempo? Não, ainda falta uma coisa. É preciso inicializar o plugin primeiro. Basta colocar lá no
extends Zend_View_Helper_Abstract
{
/**
* Exibe o tempo decorrido de um trecho de código
* baseado nos valores inicializados no plugin
* 'My_Controller_Plugin_ElapsedTime'
*
* @param int $precision
* @param string|Zend_Locale $locale
* @return float
* @throws Zend_Exception
*/
public function elapsedTime($precision = null,
$locale = null, $event =
My_Controller_Plugin_ElapsedTime::EVENT_ROUTE_STARTUP)
{
$pluginClass = 'My_Controller_Plugin_ElapsedTime';
// Verifica se o plugin foi registrado
if (!Zend_Controller_Front::getInstance()
->hasPlugin($pluginClass)) {
throw new Exception("Plugin '{$_pluginClass}' is not '
. 'registered");
}
// Primeiro vamos pegar o plugin lá do front controller,
// que já foi inicializado
$elapsedTimePlugin = Zend_Controller_Front::getInstance()
->getPlugin($pluginClass);
// Agora vamos pegar o valor calculado do tempo decorrido,
// passando como parâmetro uma daquelas constantes definidas
// na classe do plugin, pra dizer a partir de que ponto do
// código onde calcular o tempo de execução. O padrão é de
// antes da inicialização das rotas.
$elapsedTime = $elapsedTimePlugin->getElapsedTime($event);
// Retorna o tempo decorrido formatado, levando em conta o
// número de decimais a ser exibido e a localização, para
// apresentar os símbolos de separação de milhares e de
// decimais corretos
return Zend_Locale_Format::toFloat($elapsedTime, array(
'precision' => $precision, 'locale' => $locale));
}
}
application.ini uma linhazinha de código, que ele será inicializado automaticamente:resources.frontController.plugins[] = My_Controller_Plugin_ElapsedTimeAgora sim, vamos ao script
phtml chamar nosso view helper e ver ele funcionando:Essa página foi carregada em <?php echo $this->elapsedTime(2) ?> segundosAgora vamos experimentar alterar os parâmetros pra ver os tempo decorrido a partir de diferentes trechos do código:
<ul><?phpO último tipo de evento (dispatchLoopShutdown) ficou comentado por uma boa razão. Quando a view é executada, esse ponto do código ainda não foi alcançado, portanto será lançada uma excessão, como foi definido na classe do plugin. Esse caso é usado mais para fins de debug mesmo, e para ver o resultado desse cálculo, é preciso chamar o plugin diretamente do front controller. Um exemplo, é chamá-lo no index.php no fim do arquivo:
$events = array(
1 => 'routeStartup',
2 => 'routeShutdown',
3 => 'dispatchLoopStartup',
4 => 'preDispatch',
5 => 'postDispatch',
// 6 => 'dispatchLoopShutdown'
);
foreach($events as $eventId => $eventName) {
echo '<li>' . $eventName . ': '
. $this->elapsedTime(2, 'pt_BR', $eventId)
. ' segundos</li>';
}
?></ul>
Prontinho. Façam bom proveito!
$application->bootstrap()->run();
echo Zend_Controller_Front::getInstance()
->getPlugin('Case_Controller_Plugin_ElapsedTime')
->getElapsedTime(6);

