Otimização de desempenho de aplicativos PHP
O maior benefício da programação em PHP é a facilidade de aprender essa linguagem de programação e suas ricas bibliotecas. Mesmo que não saibamos muito sobre as funções que precisamos usar, podemos adivinhar como realizar uma tarefa específica.
Embora o PHP seja muito simples e fácil de aprender, ainda precisamos gastar um pouco de tempo aprendendo algumas habilidades de programação em PHP, especialmente aquelas relacionadas ao desempenho e ao uso de memória. Em PHP, existem muitos truques que nos permitem reduzir o uso de memória e melhorar o desempenho do aplicativo. Neste artigo, apresentaremos brevemente a análise de aplicativos PHP, como alterar o código do script e comparar vários valores de parâmetros antes e depois da otimização.
Ao definir procedimentos de temporização no programa e executar esses códigos repetidamente, podemos obter um conjunto de dados sobre a velocidade de execução do programa. Esses dados podem ser usados para descobrir gargalos no programa e como otimizá-lo para melhorar o desempenho do programa. aplicativo.
Talvez os leitores já tenham ouvido falar da biblioteca PEAR. Usaremos a biblioteca PEAR para criar exemplos que precisamos usar durante a análise. Essa também é a maneira mais fácil de analisar o código existente. Ela nos permite analisar o código sem usar produtos comerciais.
O nome da biblioteca que usaremos é PEAR::Benchmark e é muito útil para criar perfis e testar o desempenho do código. Esta biblioteca fornece uma classe chamada Benchmark_Timer(), que pode registrar o tempo entre uma chamada de função e a próxima chamada de função. Ao testar o desempenho do código, podemos obter um resultado detalhado da execução do script, que é muito simples, como segue:
include_once("Benchmark/Timer.php");
$bench = novo Benchmark_Timer;
$banco->start();
$bench-> setMarker('Início do script');
// Agora em estado de suspensão por alguns minutos
dormir(5);
$banco->parar();
// Obtém informações de análise do timer
print_r($bench->getProfiling());
?>
A saída após a execução do código acima é a seguinte:
Variedade
(
[0] => Matriz
(
[nome] => Iniciar
[hora] => 1013214253.05751200
[diferença] => -
[total] => 0
)
[1] => Matriz
(
[nome] => Início do script
[tempo] => 1013214253.05761100
[diferença] => 9.8943710327148E-05
[total] => 9.8943710327148E-05
)
[2] => Matriz
(
[nome] => Parar
[hora] => 1013214258.04920700
[diferença] => 4,9915959835052
[total] => 4,9916949272156
)
)
Os números acima podem parecer um conjunto desarticulado de números, mas se o tamanho do programa for maior, esses números podem ser muito úteis.
Talvez a maioria dos leitores também possa adivinhar que a primeira entrada no array é o método real de chamada da classe Benchmark_Timer(), por exemplo
$bench->start(), $bench->setMarker() e $bench->stop(). Os números associados a essas entradas são bastante simples.
[0] => Matriz
(
[nome] => Iniciar
[hora] => 1013214253.05751200
[diferença] => -
[total] => 0
)
A entrada de tempo refere-se ao carimbo de data/hora UNIX quando o método start() de Benchmark_Timer() é chamado. A entrada diff indica o intervalo de tempo entre esta chamada e a última chamada, uma vez que não há chamada anterior aqui, um Dash, a entrada total. refere-se ao tempo total que o código está em execução desde o início do teste até esta chamada específica. Vamos dar uma olhada na saída do próximo array:
[1] => Matriz
(
[nome] => Início do script
[tempo] => 1013214253.05761100
[diferença] => 9.8943710327148E-05
[total] => 9.8943710327148E-05
)
A partir dos números acima, podemos ver que após chamar $bench->start(), o programa é executado por 9,8943710327148E-05 segundos (ou seja, 0,0000989 segundos) antes de chamar $bench->setMarker(….).
Uma experiência real de teste de desempenho
Embora o exemplo acima seja bom, na verdade não é um bom exemplo para decidir como otimizar o design do código do seu site. A seguir usarei minha própria experiência pessoal como técnico de sites para ilustrar como resolver problemas de desempenho.
Eu realmente não entendo o código usado pelo site, porque ele foi desenvolvido ao longo de muitos anos com base em necessidades específicas - um módulo contém o código de conversão do site, outro módulo registra o uso do site e os outros módulos têm o seu próprio. papel de cada um. O principal desenvolvedor do site e eu percebemos que o código do site precisava ser otimizado, mas não sabíamos qual era o problema.
Para concluir a tarefa o mais rápido possível, comecei a estudar o código de script principal do site e adicionei alguns comandos $bench->setMarker() a todos os códigos de script e seus arquivos incluídos, depois analisei a saída de $bench ->getProfiling(), e fiquei surpreso com os resultados. Descobri que o problema estava em uma chamada de função relacionada ao código de conversão para obter um nome de idioma específico (como en para inglês), que foi usado centenas de vezes. em cada página. Cada vez que esta função é chamada, o código do script consulta um banco de dados MySQL para obter o nome real do idioma de uma tabela do banco de dados.
Então criamos um sistema de buffer para esse tipo de informação. Após apenas 2 dias de trabalho, melhoramos muito o desempenho do sistema e o número de visualizações de páginas aumentou 40% na primeira semana. Claro, este é apenas um exemplo de como a análise de código pode melhorar o desempenho de uma aplicação ou site da Internet.
Chamada de função de teste de desempenho
Embora Benchmark_Timer() seja particularmente útil ao analisar um script ou página da web (e seus arquivos), não é científico porque devemos carregar o script várias vezes para obter os dados analisados, e não é específico para uma determinada classe ou função . chamado.
Outra classe na biblioteca PEAR::Benchmark chamada Benchmark_Iterator pode resolver esse problema muito bem. Ela pode exibir informações de análise para uma função ou método de classe específico. Seu objetivo é ser capaz de obter resultados consistentes nos testes porque sabemos que se executarmos um script uma vez e ele levar 10 segundos para ser executado, isso não significa que sempre levará 10 segundos para ser executado todas as vezes.
De qualquer forma, vejamos alguns exemplos:
//Código para conectar ao banco de dados
include_once("DB.php");
$dsn = array(
'phptype' => 'mysql',
'hostspec' => 'localhost',
'banco de dados' => 'nome_banco de dados',
'nome de usuário' => 'nome_usuário',
'senha' => 'senha'
);
$dbh = DB::connect($dsn);
função getCreatedDate($id)
{
$dbh global;
> $stmt = "SELECIONE data_criada FROM usuários WHERE id=$id";
// Use PEAR::DB aqui
$data_criada = $dbh-> getOne($stmt);
if ((PEAR::isError($data_criada)) ||
(vazio($data_criada))) {
retornar falso;
} outro {
retornar $data_criada;
}
}
include_once 'Benchmark/Iterate.php';
$bench = novo Benchmark_Iterate;
//Executa a função getDate 10 vezes
$bench-> run(10, 'getCreatedDate', 1);
//Imprime informações de análise
print_r($banco->get());
?>
A execução do código acima produz resultados semelhantes aos seguintes:
Variedade
(
[1] => 0,055413007736206
[2] => 0,0012860298156738
[3] => 0,0010279417037964
[4] => 0,00093603134155273
[5] => 0,00094103813171387
[6] => 0,00092899799346924
[7] => 0,0010659694671631
[8] => 0,00096404552459717
[9] => 0,0010690689086914
[10] => 0,00093603134155273
[média] => 0,0064568161964417
[iterações] => 10
)
Os números acima são fáceis de entender. A entrada média representa o tempo médio de 10 execuções da função getCreatedDate(). Nos testes reais, você deve executá-lo pelo menos 1.000 vezes, mas os resultados deste exemplo são suficientes para ilustrar o problema.