Como posso medir a velocidade do código escrito em PHP? [fechadas]

118

Como posso dizer qual classe de muitas (que fazem o mesmo trabalho) é executada mais rapidamente? existe um software para medir isso?

MA Kishawy
fonte

Respostas:

195

Você tem (pelo menos) duas soluções:

O bastante "ingênuo" está usando o microtempo (verdadeiro) antes e depois de uma parte do código, para saber quanto tempo passou durante sua execução; outras respostas disseram isso e já deram exemplos, então não direi muito mais.

Esta é uma boa solução se você deseja comparar algumas instruções; como comparar dois tipos de funções, por exemplo - é melhor se feito milhares de vezes, para garantir que qualquer "elemento perturbador" seja calculado.

Algo assim, então, se você quiser saber quanto tempo leva para serializar uma matriz:

$before = microtime(true);

for ($i=0 ; $i<100000 ; $i++) {
    serialize($list);
}

$after = microtime(true);
echo ($after-$before)/$i . " sec/serialize\n";

Não é perfeito, mas é útil e não leva muito tempo para configurar.



A outra solução, que funciona muito bem se você quiser identificar qual função leva muito tempo em um script inteiro, é usar:

  • A extensão Xdebug , para gerar dados de perfil para o script
  • Software que lê os dados de criação de perfil e apresenta algo legível. Eu conheço três deles:
    • Webgrind ; interface web ; deve funcionar em qualquer servidor Apache + PHP
    • WinCacheGrind ; apenas no windows
    • KCacheGrind ; provavelmente apenas Linux e semelhante ao Linux; Esse é o que eu prefiro, aliás

Para obter arquivos de criação de perfil, você deve instalar e configurar o Xdebug; dê uma olhada na página Profiling PHP Scripts da documentação.

O que geralmente faço não é habilitar o profiler por padrão (ele gera arquivos muito grandes e torna as coisas mais lentas) , mas uso a possibilidade de enviar um parâmetro chamado XDEBUG_PROFILEGET data, para ativar o profiling apenas para a página que preciso.
A parte relacionada à criação de perfil do meu php.ini é assim:

xdebug.profiler_enable = 0              ; Profiling not activated by default
xdebug.profiler_enable_trigger = 1      ; Profiling activated when requested by the GET parameter
xdebug.profiler_output_dir = /tmp/ouput_directory
xdebug.profiler_output_name = files_names

(Leia a documentação para mais informações)

Esta captura de tela é de um programa C ++ em KcacheGrind: (fonte: sourceforge.net ) Você obterá exatamente o mesmo tipo de coisa com scripts PHP ;-) (Com KCacheGrind, quero dizer; WinCacheGrind não é tão bom quanto KCacheGrind ... )http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif



Isso permite que você tenha uma boa visão do que leva tempo em sua aplicação - e às vezes ajuda definitivamente a localizar a função que está deixando tudo lento ^^

Observe que o Xdebug conta o tempo de CPU gasto pelo PHP; quando o PHP está esperando uma resposta de um Banco de Dados (por exemplo), ele não está funcionando; apenas esperando. Portanto, o Xdebug pensará que a solicitação do DB não leva muito tempo!
Isso deve ser perfilado no servidor SQL, não PHP, então ...


Espero que isso seja útil :-)
Divirta-se!

Pascal MARTIN
fonte
1
Existe um Windows build do QCacheGrind :-) sourceforge.net/projects/qcachegrindwin
François Breton
43

Para coisas rápidas, eu faço isso (em PHP):

$startTime = microtime(true);
doTask(); // whatever you want to time
echo "Time:  " . number_format(( microtime(true) - $startTime), 4) . " Seconds\n";

Você também pode usar um criador de perfil como http://xdebug.org/ .

Scott Saunders
fonte
2
Para obter precisão adicional, sugiro (a) usar um loop e calcular a média do tempo e (b) usar arquivos separados para cada coisa que você está testando. Se você tiver vários tempos em um script, a ordem deles pode fazer a diferença às vezes.
DisgruntledGoat
9

Fiz uma aula de tempo simples, talvez seja útil para alguém:

class TimingHelper {

    private $start;

    public function __construct() {
        $this->start = microtime(true);
    }

    public function start() {
        $this->start = microtime(true);
    }

    public function segs() {
        return microtime(true) - $this->start;
    }

    public function time() {
        $segs = $this->segs();
        $days = floor($segs / 86400);
        $segs -= $days * 86400;
        $hours = floor($segs / 3600);
        $segs -= $hours * 3600;
        $mins = floor($segs / 60);
        $segs -= $mins * 60;
        $microsegs = ($segs - floor($segs)) * 1000;
        $segs = floor($segs);

        return 
            (empty($days) ? "" : $days . "d ") . 
            (empty($hours) ? "" : $hours . "h ") . 
            (empty($mins) ? "" : $mins . "m ") . 
            $segs . "s " .
            $microsegs . "ms";
    }

}

Usar:

$th = new TimingHelper();
<..code being mesured..>
echo $th->time();
$th->start(); // if it's the case
<..code being mesured..>
echo $th->time();

// result: 4d 17h 34m 57s 0.00095367431640625ms 
Nelson Teixeira
fonte
Você digitou incorretamente: é echo, não$echo
SuN
9

Atualização de 2020

Já se passaram muitos anos desde a última vez que respondi a essas perguntas, então achei que isso merece uma atualização sobre o panorama do APM.

  • O AppDynamics foi comprado pela Cisco e a conta gratuita para sempre que eles costumavam oferecer foi retirada de seu site.
  • NewRelic baixou seus preços de $ 149 / mês / host para $ 25 / mês / host para competir com o recém-chegado ao mercado de APM, Datadog, que oferece $ 31 / mês / host.
  • Os recursos do Datadog APM ainda são claros e deixam muito a desejar. No entanto, vejo que eles estão aprimorando e melhorando ao longo do próximo ano.
  • Ruxit foi comprado pela Dynatrace. Sem surpresas aqui, já que o Ruxit é construído por ex-funcionários da Dynatrace. Isso permitiu que a Dynatrace se transformasse em um modelo verdadeiramente SaaS para melhor. Diga adeus a esse cliente Java volumoso, se quiser.
  • Agora também existem opções de código aberto / gratuito. Caixa Apache Skywalking que é muito popular na China entre suas empresas de tecnologia superior e PinPoint que oferece uma demo que você pode experimentar antes de instalar. Ambos exigem que você gerencie a hospedagem, então prepare-se para ativar algumas máquinas virtuais e passar algum tempo com a instalação e configuração.
  • Não tentei nenhuma dessas soluções de APM de código aberto, então não estou em posição de recomendá-las, no entanto, gerenciei pessoalmente a implantação de todas essas soluções de APM para várias organizações no local ou na nuvem para centenas de aplicativos / microsserviços. Portanto, posso dizer com confiança, você não pode dar errado com nenhum dos fornecedores se eles se enquadrarem em sua conta.


Respondido originalmente em outubro de 2015

Aqui está uma resposta direta à sua pergunta

existe um software para medir isso?

Sim existe. Estou me perguntando por que ninguém ainda não mencionou isso. Embora as respostas sugeridas acima pareçam adequadas para uma verificação rápida, não são escaláveis ​​a longo prazo ou para um projeto maior.

Por que não usar uma ferramenta Application Performance Monitoring (APM) que foi construída exatamente para isso e muito mais. Confira NewRelic, AppDynamics, Ruxit (todos têm versão gratuita) para monitorar o tempo de execução, o uso de recursos, o rendimento de cada aplicativo até o nível do método.

na-98
fonte
6

Se você quiser testar rapidamente o desempenho de um framework, você pode colocar o arquivo index.php

//at beginning
$milliseconds = round(microtime(true) * 1000);

//and at the end
echo round(microtime(true) * 1000) - $milliseconds;

Toda vez, você obterá tempo de execução em milissegundos . Porque microssegundos não são muito úteis para testar um caso de estrutura.

tasmaniski
fonte
5

Tenho usado o XHProf recentemente http://pecl.php.net/package/xhprof . Foi originalmente desenvolvido pelo Facebook e vem com uma interface web decente.

Jason
fonte
4

Gostaria de compartilhar com vocês uma função criada por mim mesmo que uso para medir a velocidade de qualquer função existente com até 10 argumentos:

function fdump($f_name='', $f_args=array()){

    $f_dump=array();
    $f_result='';

    $f_success=false;

    $f_start=microtime();
    $f_start=explode(' ', $f_start);
    $f_start=$f_start[1] + $f_start[0];

    if(function_exists($f_name)){

        if(isset($f_args[0])&&is_array($f_args[0])){
            if($f_result=$f_name($f_args)){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[1])){
            if($f_result=$f_name($f_args[0])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[2])){
            if($f_result=$f_name($f_args[0],$f_args[1])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[3])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[4])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[5])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[6])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[7])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[8])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[9])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[10])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8],$f_args[9])){
                $f_success=true;
            }
        }
    }
    $f_end=microtime();
    $f_end=explode(' ', $f_end);
    $f_end=$f_end[1] + $f_end[0];

    $f_time=round(($f_end - $f_start), 4);
    $f_dump['f_success']=$f_success;
    $f_dump['f_time']=$f_time;
    $f_dump['f_result']=$f_result;

    var_dump($f_dump);exit;

    //return $f_result;

}

Exemplo

function do_stuff($arg1='', $arg2=''){
    return $arg1.' '.$arg2;
}

fdump('do_stuff',array('hello', 'world'));

Devoluções

  array(3) {
    ["f_success"]=>
    bool(true)
    ["f_time"]=>
    float(0)            //too fast...
    ["f_result"]=>
    string(11) "hello world"
  }
RafaSashi
fonte
3

Se for algo que pode ser testado fora do contexto da Web, eu apenas uso o timecomando Unix .

caos
fonte
3

Zend Studio possui suporte embutido para criação de perfil usando XDebug ou ZendDebugger. Ele fará o perfil de seu código, informando exatamente quanto tempo cada função demorou. É uma ferramenta fantástica para descobrir onde estão seus gargalos.

OverloadUT
fonte
1

Você pode usar coisas básicas como armazenar carimbos de data / hora ou microtime () antes e depois de uma operação para calcular o tempo necessário. Isso é fácil de fazer, mas não muito preciso. Talvez a melhor solução seja o Xdebug , nunca trabalhei com ele, mas parece ser o depurador / profiler de PHP mais conhecido que posso encontrar.

Alex
fonte