Maneira mais simples de criar um perfil de um script PHP

289

Qual é a maneira mais fácil de criar um perfil de script PHP?

Eu adoraria colocar algo que me mostre um despejo de todas as chamadas de função e quanto tempo elas levaram, mas também estou bem em colocar algo em torno de funções específicas.

Eu tentei experimentar a função microtime :

$then = microtime();
myFunc();
$now = microtime();

echo sprintf("Elapsed:  %f", $now-$then);

mas isso às vezes me dá resultados negativos. Além disso, é muito problemático espalhar isso por todo o meu código.

Mark Biek
fonte
7
ei Mark, confira este comentário para ajudá-lo a resolver os comentários negativos: ro.php.net/manual/en/function.microtime.php#99524
Mina
16
Esse comentário vinculado por @Midiane não faz sentido. Se pareceu resolver o problema do comentarista, deve ter sido uma coincidência. Usando apenas microtime()vai levar a expressões às vezes avaliando como: "0.00154800 1342892546" - "0.99905700 1342892545", que irá avaliar como: 0.001548 - 0.999057. Você pode usar microtime( TRUE )para evitar esse problema, como apontado por @luka.
JMM 21/07

Respostas:

104

A extensão PECL APD é usada da seguinte maneira:

<?php
apd_set_pprof_trace();

//rest of the script
?>

Depois, analise o arquivo gerado usando pprofp.

Exemplo de saída:

Trace for /home/dan/testapd.php
Total Elapsed Time = 0.00
Total System Time  = 0.00
Total User Time    = 0.00


Real         User        System             secs/    cumm
%Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
--------------------------------------------------------------------------------------
100.0 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0000   0.0009            0 main
56.9 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0005   0.0005            0 apd_set_pprof_trace
28.0 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 preg_replace
14.3 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 str_replace

Aviso: a versão mais recente do APD é datada de 2004, a extensão não é mais mantida e tem vários problemas de compatibilidade (consulte os comentários).

Vincent
fonte
19
A extensão APD está quebrada no php 5.4.
Skynet
Em resposta ao user457015, consegui fazê-lo funcionar em um site executando o wordpress 3.8.1 e o PHP 5.3.10 e parecia funcionar muito bem.
Supernovah
1
@Supernovah, user457015 disse PHP 5.4. Ele não disse que estava quebrado no PHP 5.3.
Magnus #
@ user1420752 Estou executando o 5.3.27 e também não está executando lá. Eu recebo um erro de função indefinido.
Fractaly 13/08/16
2
A última versão do APD é de 2004 (!) Ele não funciona com o PHP 7. Ao tentar instalar o PHP 5 com pecl install apd, ele fornece uma mensagem de erro sobre "config.m4". Parece que você precisa instalá-lo da fonte, o que eu ainda não tentei. Sério, não existe uma ferramenta moderna e atualizada de criação de perfil baseada em CLI para PHP que é instalada com o Homebrew, requer configuração mínima e fornece saída facilmente legível por humanos?
forthrin 29/08/16
267

Você quer xdebug, eu acho. Instale-o no servidor, ligue-o, bombeie a saída pelo kcachegrind (para linux) ou wincachegrind (para windows) e ele mostrará alguns gráficos bonitos que detalham os horários exatos, contagens e uso de memória (mas você precisa de outra extensão para isso).

É demais, sério: D

mercutio
fonte
6
Achei isso muito mais fácil de implementar do que a solução APD. Mas talvez seja porque, por algum motivo, o APD não tenha sido compilado corretamente no meu sistema. Também os gráficos de kcachegrind eram tão bonitos quanto o prometido.
Wxs
1
@EvilPuppetMaster, você precisa compilar o php com --enable-memory-limit ou usar uma versão php mais moderna. Veja xdebug.org/docs/basic#xdebug_memory_usage
mercutio
52
O xdebug + webgrind rapidamente se tornou minha arma de escolha para criação de perfil rápido e fácil. code.google.com/p/webgrind
xkcd150 27/04/10
6
xdebug + xdebug_start_trace () + xdebug_stop_trace () = vitória
quano
3
Foi muito fácil começar a trabalhar no Windows com o XAMPP. Já tinha netbeans configurados para xdebug. A única coisa que você precisa fazer é alterar uma configuração de xdebug no php.ini para xdebug.profiler_output_name = "cachegrind.out.% T-% s" ou nenhuma saída será gerada. Requer reinicialização do apache.
iniciante_
97

Não são necessárias extensões, basta usar essas duas funções para criar um perfil simples.

// Call this at each point of interest, passing a descriptive string
function prof_flag($str)
{
    global $prof_timing, $prof_names;
    $prof_timing[] = microtime(true);
    $prof_names[] = $str;
}

// Call this when you're done and want to see the results
function prof_print()
{
    global $prof_timing, $prof_names;
    $size = count($prof_timing);
    for($i=0;$i<$size - 1; $i++)
    {
        echo "<b>{$prof_names[$i]}</b><br>";
        echo sprintf("&nbsp;&nbsp;&nbsp;%f<br>", $prof_timing[$i+1]-$prof_timing[$i]);
    }
    echo "<b>{$prof_names[$size-1]}</b><br>";
}

Aqui está um exemplo, chamando prof_flag () com uma descrição em cada ponto de verificação e prof_print () no final:

prof_flag("Start");

   include '../lib/database.php';
   include '../lib/helper_func.php';

prof_flag("Connect to DB");

   connect_to_db();

prof_flag("Perform query");

   // Get all the data

   $select_query = "SELECT * FROM data_table";
   $result = mysql_query($select_query);

prof_flag("Retrieve data");

   $rows = array();
   $found_data=false;
   while($r = mysql_fetch_assoc($result))
   {
       $found_data=true;
       $rows[] = $r;
   }

prof_flag("Close DB");

   mysql_close();   //close database connection

prof_flag("Done");
prof_print();

A saída fica assim:

Iniciar
   0.004303
Conectar ao DB
   0.003518
Executar consulta
   0.000308
Recuperar dados
   0.000009
Fechar DB
   0.000049
Concluído

TimH - Codidact
fonte
37

Postando minha referência na SO Documentation beta, que está ficando offline.

Criação de perfil com o XDebug

Uma extensão para PHP chamada Xdebug está disponível para auxiliar na criação de perfil de aplicativos PHP , bem como na depuração em tempo de execução. Ao executar o criador de perfil, a saída é gravada em um arquivo em um formato binário chamado "cachegrind". Os aplicativos estão disponíveis em cada plataforma para analisar esses arquivos. Nenhuma alteração no código do aplicativo é necessária para executar essa criação de perfil.

Para habilitar a criação de perfil, instale a extensão e ajuste as configurações do php.ini. Algumas distribuições Linux vêm com pacotes padrão (por exemplo, php-xdebugpacote do Ubuntu ). Em nosso exemplo, executaremos o perfil opcionalmente com base em um parâmetro de solicitação. Isso nos permite manter as configurações estáticas e ativar o criador de perfil apenas conforme necessário.

# php.ini settings
# Set to 1 to turn it on for every request
xdebug.profiler_enable = 0
# Let's use a GET/POST parameter to turn on the profiler
xdebug.profiler_enable_trigger = 1
# The GET/POST value we will pass; empty for any value
xdebug.profiler_enable_trigger_value = ""
# Output cachegrind files to /tmp so our system cleans them up later
xdebug.profiler_output_dir = "/tmp"
xdebug.profiler_output_name = "cachegrind.out.%p"

Em seguida, use um cliente da Web para fazer uma solicitação ao URL do seu aplicativo que você deseja criar um perfil, por exemplo,

http://example.com/article/1?XDEBUG_PROFILE=1

À medida que a página é processada, ela será gravada em um arquivo com um nome semelhante a

/tmp/cachegrind.out.12345

Por padrão, o número no nome do arquivo é a identificação do processo que o escreveu. Isso é configurável com a xdebug.profiler_output_nameconfiguração.

Observe que ele gravará um arquivo para cada solicitação / processo PHP executado. Portanto, por exemplo, se você deseja analisar uma postagem de formulário, um perfil será gravado para a solicitação GET exibir o formulário HTML. O parâmetro XDEBUG_PROFILE precisará ser passado para a solicitação POST subsequente para analisar a segunda solicitação que processa o formulário. Portanto, ao criar um perfil, às vezes é mais fácil executar curl para postar um formulário diretamente.

Analisando a saída

Depois de gravado, o cache do perfil pode ser lido por um aplicativo como o KCachegrind ou o Webgrind . O PHPStorm, um popular IDE do PHP, também pode exibir esses dados de criação de perfil .

KCachegrind

O KCachegrind, por exemplo, exibirá informações, incluindo:

  • Funções executadas
  • Tempo de chamada, próprio e inclusivo das chamadas de função subsequentes
  • Número de vezes que cada função é chamada
  • Gráficos de chamadas
  • Links para código fonte

O que procurar

Obviamente, o ajuste de desempenho é muito específico para os casos de uso de cada aplicativo. Em geral, é bom procurar:

  • Chamadas repetidas para a mesma função que você não esperaria ver. Para funções que processam e consultam dados, essas podem ser as principais oportunidades para o cache do seu aplicativo.
  • Funções de execução lenta. Onde o aplicativo está gastando a maior parte do tempo? a melhor recompensa no ajuste de desempenho está focada nas partes do aplicativo que consomem mais tempo.

Nota : O Xdebug, e em particular seus recursos de criação de perfil, consomem muitos recursos e diminuem a execução do PHP. É recomendável não executá-los em um ambiente de servidor de produção.

Matt S
fonte
3
Para completar a lista de ferramentas para analisar o cache do perfil: PhpStorm também tem uma ferramenta para visualizar o cache do perfil
peterchaula
1
@ Peter Esqueci PHPStorm tem esse recurso. Adicionei-o com um link para a documentação. Obrigado!
Matt S
Alguma maneira de obter um relatório de texto (não GUI) diretamente no servidor?
Alexander Shcheblikin
1
@ Mark, você pode marcar isso como resposta, por favor. A resposta atual estava desatualizada, mesmo quando postada e não funciona há muitos anos. Isso funciona e não conheço um método melhor.
Mawg diz que restabelece Monica em
24

Se subtrair microtimes fornecer resultados negativos, tente usar a função com o argumento true( microtime(true)). Com true, a função retorna um float em vez de uma string (como acontece se for chamada sem argumentos).

luka
fonte
24

Honestamente, vou argumentar que o uso do NewRelic para criação de perfil é o melhor.

É uma extensão PHP que parece não diminuir o tempo de execução e eles fazem o monitoramento para você, permitindo uma pesquisa decente. Na versão cara, eles permitem drill down pesado (mas não podemos pagar pelo modelo de preços).

Mesmo assim, mesmo com o plano gratuito / padrão, é óbvio e simples onde está a maioria das frutas baixas. Eu também gosto que ele também pode dar uma idéia sobre as interações com o banco de dados.

captura de tela de uma das interfaces ao criar um perfil

zeroasterisk
fonte
16
A New Relic parece promissora, com certeza. No entanto, a parte "Divulgação dos dados do aplicativo" de sua Política de Privacidade me repeliu instantaneamente. Imho, compartilhar partes do código-fonte proprietário com terceiros é um pouco demais.
Cengiz
8
Não estamos aqui em defesa deles, mas parece que "Dados do Aplicativo" são apenas informações de desempenho e informações de configuração do sistema, não o código-fonte do aplicativo.
David Shields
Fir meu novo relíquia está mostrando meu "WebTransaction", como 99% do tempo, e não tem a conta pro para "ApplicationTraces"
Karthik T
1
tente se inscrever em: newrelic.com/rackspace <deve dar-lhe "padrão" de graça
zeroasterisk
15

Perfil do pobre homem, sem extensões necessárias. Suporta perfis aninhados e porcentagem do total:

function p_open($flag) {
    global $p_times;
    if (null === $p_times)
        $p_times = [];
    if (! array_key_exists($flag, $p_times))
        $p_times[$flag] = [ 'total' => 0, 'open' => 0 ];
    $p_times[$flag]['open'] = microtime(true);
}

function p_close($flag)
{
    global $p_times;
    if (isset($p_times[$flag]['open'])) {
        $p_times[$flag]['total'] += (microtime(true) - $p_times[$flag]['open']);
        unset($p_times[$flag]['open']);
    }
}

function p_dump()
{
    global $p_times;
    $dump = [];
    $sum  = 0;
    foreach ($p_times as $flag => $info) {
        $dump[$flag]['elapsed'] = $info['total'];
        $sum += $info['total'];
    }
    foreach ($dump as $flag => $info) {
        $dump[$flag]['percent'] = $dump[$flag]['elapsed']/$sum;
    }
    return $dump;
}

Exemplo:

<?php

p_open('foo');
sleep(1);
p_open('bar');
sleep(2);
p_open('baz');
sleep(3);
p_close('baz');
sleep(2);
p_close('bar');
sleep(1);
p_close('foo');

var_dump(p_dump());

Rendimentos:

array:3 [
  "foo" => array:2 [
    "elapsed" => 9.000766992569
    "percent" => 0.4736904954747
  ]
  "bar" => array:2 [
    "elapsed" => 7.0004580020905
    "percent" => 0.36841864946596
  ]
  "baz" => array:2 [
    "elapsed" => 3.0001420974731
    "percent" => 0.15789085505934
  ]
]
bispo
fonte
13

O PECL XHPROF também parece interessante. Possui interface HTML clicável para visualizar relatórios e documentação bastante direta . Ainda tenho que testá-lo.

Josef Sábl
fonte
Parece que não está recebendo muito amor. Última atualização em 2009, nenhum pacote PEAR para 5.3, 5.4 e além ...
dland 02/02
1
Facebook criou um garfo com apoio através de php 5.5 github.com/facebook/xhprof
borkencode
Verifique também este garfo, que propõe alguns ajustes adicionais: github.com/preinheimer/xhprof
Fedir RYKHTIK 04/04
O xhprof.io fornece GUI para dados coletados usando XHProf, além de capacidade de armazenar dados no banco de dados para fins de análise histórica. Eu sou o autor desta última implementação.
Gajus
10

Eu gosto de usar o phpDebug para criação de perfil. http://phpdebug.sourceforge.net/www/index.html

Ele gera todo o uso de tempo / memória para qualquer SQL usado, bem como para todos os arquivos incluídos. Obviamente, ele funciona melhor em códigos abstraídos.

Para perfis de função e classe, usarei microtime()+ get_memory_usage()+ get_peak_memory_usage().

Eric Lamb
fonte
6

Para benchmarking, como no seu exemplo, eu uso o pacote Pear Benchmark . Você define marcadores para medição. A classe também fornece alguns auxiliares de apresentação ou você pode processar os dados como achar melhor.

Na verdade, eu o envolvi em outra classe com um método __destruct. Quando um script sai, a saída é registrada via log4php no syslog; portanto, tenho muitos dados de desempenho para trabalhar.

Gary Richardson
fonte
3

O XDebug não é estável e nem sempre está disponível para uma determinada versão do php. Por exemplo, em alguns servidores, eu continuo executando o php-5.1.6, - é o que vem com o RedHat RHEL5 (e o btw ainda recebe atualizações para todas as questões importantes), e o XDebug recente nem compila com este php. Então, acabei mudando para o depurador DBG. O benchmarking php fornece tempo para funções, métodos, módulos e até linhas.

user2221743
fonte
2

Vocês todos deveriam definitivamente conferir este novo perfil de php.

https://github.com/NoiseByNorthwest/php-spx

Redefine a maneira como os criadores de perfil php coletam e apresentam o resultado. Em vez de emitir apenas um número total de chamadas de função específicas e o tempo total gasto para executá-lo - o PHP-SPX apresenta toda a linha do tempo da execução de solicitações de uma maneira perfeitamente legível. Abaixo está a tela da GUI que ela fornece.

insira a descrição da imagem aqui

Jacek Dziurdzikowski
fonte