PHP Opcode: melhore o desempenho da aplicação sem alterar seu código

O código de operação PHP gerado pelo motor PHP é fortemente influenciado pela forma como você escreve seu código, não apenas em termos de número de declarações para concluir uma tarefa. Claramente, isso importa muito e acho que é óbvio para você.

O que pode ser menos óbvio é que até a sintaxe do código pode mudar completamente o código de operação gerado, causando muito overheard para o CPU da máquina para executar o mesmo código exatamente.

nos últimos anos, o meu produto SaaS cresceu muito e deu-me a oportunidade de mergulhar cada vez mais fundo em técnicas de otimização para executar minha carga de trabalho o mais eficientemente possível.

Os resultados que vi são impressionantes e ajudaram-me muito a desbloquear o cash flow livre para continuar desenvolvendo minha jornada SaaS.

Neste ponto, o processo PHP dentro do meu produto SaaS está processando mais de 1,2 bilhão (com “b”) de pacotes de dados a cada dia em uma máquina com 2vCPU e 8GB de memória.

Eu usei um grupo de autoescala do AWS para ter mais flexibilidade em caso de picos impredecíveis, mas raramente adiciona uma segunda máquina (uma/duas vezes por semana).

Vamos entrar no tópico do artigo. Acho que você encontrará muito interessante.

O que é Código de Operação PHP? O código de operação PHP significa

operação de código, e refere-se às instruções de nível baixo que são executadas pelo motor PHP após o código fonte PHP que você escreveu ter sido compilado. Em PHP, a compilação do código acontece em tempo de execução: basicamente, a primeira vez que seu código é pego pelo motor PHP, ele será compilado para este código amigável à máquina, armazenado em cache (então o motor não compila o mesmo código novamente) e então executado.

Esta é uma representação simples do processo:

Cache de Opcodes PHP

O cache de opcodes do PHP permite economizar três passos no processo de execução do código: análise do código PHP bruto, tokenização e compilação.

Uma vez que os opcodes forem gerados pela primeira vez, eles são armazenados em memória para serem reutilizados nas solicitações subsequentes. Isso reduz a necessidade do motor PHP de recompilar o mesmo código PHP a cada execução, economizando muito consumo de CPU e memória.

O cache de opcodes mais comumente usado no PHP é o OPCache, e está incluído por padrão a partir da versão 5.5 até as versões recentes. Ele é altamente eficiente e amplamente suportado.

O cache do bytecode pré-compilado do script exige que o cache seja invalidado após cada implantação. Isso é necessário porque se arquivos alterados tiverem a versão do bytecode no cache, o PHP continuará executando a versão antiga do código até que você limpe o cache de opcodes, portanto, o novo código será compilado novamente, gerando um novo item de cache.

Como Investigações de Opcode PHP

Para entender como diferentes sintaxes podem impactar o opcode do script, precisamos de uma maneira de pegar o código compilado gerado pelo motor PHP.

Existem duas maneiras de obter o opcode.

Funções Nativas do OPCache

Se você tiver a extensão OPCache habilitada em seu computador, você pode usar suas funções nativas para obter o opcode de um arquivo PHP específico:

PHP

 

VLD (Vulcan Logic Disassembler) PHP Extension

VLD é uma extensão popular de PHP que desmonta o código compilado PHP e emite o opcode. É uma ferramenta poderosa para entender como o PHP interpreta e executa seu código. Assim que instalado, você pode executar um script PHP com VLD ativado usando o comando php com as opções -d:

Shell

 

A saída incluirá informações detalhadas sobre o opcode compilado, incluindo cada operação, sua linha de código associada e muito mais.

Use 3v4l (Acrônimo para EVAL)

3v4l é uma ferramenta online muito útil que permite que você veja o opcode gerado por um código PHP que você digita no editor. Basicamente, é um servidor PHP com VLD instalado para pegar a saída de VLD e mostrar o opcode no navegador.

Como é grátis, vamos usar esta ferramenta online para as próximas análises.

Como Gerar Opcode PHP Eficiente

3v4l é perfeito para entender como a sintaxe de código que usamos pode influenciar o opcode PHP resultante de forma boa ou má. Vamos começar a colar o código abaixo em 3v4l. Manter a configuração “todas as versões suportadas” e clicar em “eval”.

PHP

 

Após executar o código, uma barra de menu aparecerá no final. Navegue até a aba VLD para visualizar o opcode correspondente.

Shell

 

Note que a primeira operação é INIT_NS_FCALL_BY_NAME. O interpretador constrói o nome da função usando o namespace do arquivo atual, mas não existe no namespace App\Example — então como funciona?

O interpretador verificará se a função existe no namespace atual. Se não existir, ele tentará chamar a função correspondente do core.

Aqui temos a oportunidade de dizer ao interpretador para evitar esta verificação dupla e executar diretamente a função do core.

Tente adicionar um backslash (\) antes de strlen e clique em “eval”:

PHP

 

No painel VLD, você agora pode ver o opcode com apenas uma instrução.

Porque você comunicou a localização exata da função, não há necessidade de considerar nenhuma alternativa.

Se você não quiser usar o backslash, você pode importar a função como qualquer outra classe do namespace raiz:

PHP

 

Aproveite as Otimizações Automáticas de Opcode

Há também muitos automatismos internos do motor PHP para gerar um opcode otimizado avaliando expressões estáticas em avanço. Esta foi uma das razões mais importantes para o grande melhoramento de desempenho do PHP a partir da versão 7.x.

Ser ciente destas dinâmicas pode realmente ajudar você a reduzir o consumo de recursos e poupar custos. Assim que eu fiz esta pesquisa, comecei a usar estas truques em todo o código.

Deixe-me mostrar um exemplo usando as constantes do PHP. Execute este script no 3v4l:

PHP

 

Veja as duas primeiras linhas do opcode PHP:

FETCH_CONSTANT tenta obter o valor de PHP_OS do namespace atual e irá procurar no namespace global, já que não existe aqui. Em seguida, a instrução IS_IDENTICAL executa a instrução IF.

Agora tente adicionar a barra invertida a uma constante:

PHP

 

Como você pode ver no opcode, o motor não precisa tentar buscar a constante porque agora está claro onde ela está, e como é um valor estático, já está na memória.

Além disso, a instrução IF desapareceu porque o outro lado da instrução IS_IDENTICAL é uma string estática (‘Linux’), então o IF pode ser marcado como “true” sem a sobrecarga de interpretá-lo em cada execução.

É por isso que você tem muito poder para influenciar o desempenho final do seu código PHP.

Conclusão

Espero que tenha sido um tópico interessante. Como mencionei no início do artigo, estou obtendo muitos benefícios ao usar essa tática e, de fato, elas também são utilizadas em nossos pacotes.

Você pode ver um exemplo aqui de como usei essas dicas em nosso pacote PHP para otimizar seu desempenho.

Se você quiser saber mais sobre os desafios de construir uma empresa orientada por desenvolvedores, você pode me seguir no LinkedIn.

Source:
https://dzone.com/articles/php-opcode-improve-application-performance