Pergunta

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

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

Eu tentei experimentar com o microtempo função:

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

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

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

Foi útil?

Solução

O PECL APD extensão é usada da seguinte forma:

<?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 última versão do APD é datada de 2004, a extensão não é mais mantido e tem vários problemas de compatibilidade (ver comentários).

Outras dicas

Você quer xdebug Eu penso.Instale-o no servidor, ligue-o, bombeie a saída através kcachegrind (para Linux) ou wincachegrind (para Windows) e mostrará alguns gráficos bonitos que detalham os tempos exatos, contagens e uso de memória (mas você precisará de outra extensão para isso).

É demais, sério :D

Nenhuma extensão é necessária, basta usar essas duas funções para criar perfis 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 é assim:

Começar
   0.004303
Conecte-se ao banco de dados
   0.003518
Executar consulta
   0.000308
Recuperar dados
   0.000009
Fechar banco de dados
   0.000049
Feito

Postagem cruzada de minha referência da documentação SO beta que está ficando offline.

Criação de perfil com XDebug

Uma extensão para PHP chamada Xdebug está disponível para auxiliar criação de perfil de aplicativos PHP, bem como depuração em tempo de execução.Ao executar o criador de perfil, a saída é gravada em um arquivo em formato binário chamado "cachegrind".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 o perfil, instale a extensão e ajuste as configurações do php.ini.Algumas distribuições Linux vêm com pacotes padrão (por exemploUbuntu php-xdebug pacote).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 quando 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 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 grava em um arquivo com um nome semelhante a

/tmp/cachegrind.out.12345

Por padrão, o número no nome do arquivo é o ID do processo que o escreveu.Isto é configurável com o xdebug.profiler_output_name contexto.

Observe que ele gravará um arquivo para cada solicitação/processo PHP executado.Assim, por exemplo, se você deseja analisar uma postagem de formulário, um perfil será escrito 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 perfil, às vezes é mais fácil executar curl para POST um formulário diretamente.

Analisando a saída

Uma vez gravado, o cache do perfil pode ser lido por um aplicativo como KCachegrind ou Web Grind.PHPStorm, um IDE PHP popular, também pode exibir esses dados de perfil.

KCachegrind

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

  • Funções executadas
  • Tempo de chamada, tanto em si quanto incluindo chamadas de função subsequentes
  • Número de vezes que cada função é chamada
  • Gráficos de chamadas
  • Links para o 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 seu aplicativo armazenar em cache.
  • Funções de execução lenta.Onde o aplicativo passa a maior parte do tempo?a melhor recompensa no ajuste de desempenho é focar nas partes do aplicativo que consomem mais tempo.

Observação:O Xdebug, e em particular seus recursos de criação de perfil, consomem muitos recursos e retardam a execução do PHP.Recomenda-se não executá-los em um ambiente de servidor de produção.

Se a subtração de microtempos 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).

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

É uma extensão PHP que não parece desacelerar o tempo de execução e eles fazem o monitoramento para você, permitindo um detalhamento decente.Na versão cara, eles permitem detalhamentos pesados ​​(mas não podemos arcar com seu modelo de precificação).

Ainda assim, mesmo com o plano gratuito/padrão, é óbvio e simples onde está a maior parte dos frutos mais fáceis de alcançar.Também gosto que isso possa lhe dar uma ideia sobre as interações do banco de dados.

screenshot of one of the interfaces when profiling

PECL XHPROF parece interessante também.Tem interface HTML clicável para visualizar relatórios e bastante simples documentação.Ainda não testei.

Perfil do pobre homem, sem necessidade de extensões.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
  ]
]

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

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

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

eu daria desafiadoramente Fogo Preto uma tentativa.

Existe esse virtualBox que eu montei usando fantoche, para testar diferentes frameworks php que acompanham o BlackFire, sinta-se à vontade para fazer um fork e/ou distribuir, se necessário :)

https://github.com/webit4me/PHPFrameworks

Para benchmarking, como no seu exemplo, eu uso o referência de pêra pacote.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 é encerrado, a saída é registrada via log4php no syslog, então tenho muitos dados de desempenho para trabalhar.

O XDebug não é estável e nem sempre está disponível para uma versão específica do php.Por exemplo, em alguns servidores eu ainda executo o php-5.1.6, - é o que vem com o RedHat RHEL5 (e aliás ainda recebe atualizações para todos os problemas importantes), e o XDebug recente nem mesmo compila com este php.Então acabei mudando para Depurador DBGIsso é benchmarking de php fornece tempo para funções, métodos, módulos e até linhas.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top