PHP Opcode: Melhorar o Desempenho de Aplicações sem Alterar seu Código

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

O que pode ser menos óbvio é que até mesmo a sintaxe do código pode mudar completamente o opcode gerado, causando muita sobrecarga para a CPU da máquina executar o mesmo código exato.

Nos últimos anos, meu produto SaaS cresceu muito e me deu a oportunidade de aprofundar cada vez mais nas técnicas de otimização para executar minha carga de trabalho da maneira mais eficiente possível.

Os resultados que vi são impressionantes e me ajudaram muito a liberar fluxo de caixa livre para continuar desenvolvendo minha jornada SaaS.

Neste momento, o processo PHP dentro do meu produto SaaS está processando mais de 1,2 bilhão (com “b”) de pacotes de dados todos os dias em uma máquina com 2vCPU e 8GB de memória. Uso um grupo de dimensionamento automático da AWS para ter mais flexibilidade em caso de picos imprevisíveis, mas raramente adiciona uma segunda máquina (uma ou duas vezes por semana).

Vamos entrar no tópico do artigo. Acho que você vai achar muito interessante.

O que é o PHP Opcode?

Opcode PHP significa código de operação e refere-se às instruções de baixo nível que são executadas pelo mecanismo PHP depois que o código-fonte PHP que você escreveu foi compilado.

No PHP, a compilação do código ocorre em tempo de execução: basicamente, na primeira vez em que seu código é recebido pelo mecanismo PHP, ele será compilado neste código compatível com a máquina, em cache (para que o mecanismo não compile o mesmo código novamente) e depois executado.

Este é uma representação simples do processo:

Cache de Opcodes PHP

Ao cachear os opcodes PHP, você consegue 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 em pedidos subsequentes. Isto reduz a necessidade do motor PHP de recompilar o mesmo código PHP a cada execução, economizando muito tempo de CPU e memória.

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

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

Como Investigaar Opcodes PHP

Para entender como a sintaxe diferente pode afetar o opcode do script, precisamos de uma maneira de obter o código compilado gerado pelo motor PHP.

Existem duas maneiras de obter os opcodes.

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 os opcodes de um arquivo PHP específico:

PHP

 

VLD (Vulcan Logic Disassembler) PHP Extension

VLD é uma extensão popular de PHP que desassemeta o código PHP compilado e exibe 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 habilitado 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, a linha de código associada e muito mais.

Use o 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 o VLD instalado, para pegar a saída do 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

O 3v4l é perfeito para entender como a sintaxe de código que usamos pode influenciar o opcode PHP resultante de bom ou mau modo. Vamos começar a colar o código abaixo no 3v4l. Mantenha a configuração “todas as versões suportadas” e clique em “eval”.

PHP

 

Após executar o código, uma lista 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 é que isso 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

 

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

Porque você comunicou a localização exata da função, ela não precisa 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 de Opcode Automáticas

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

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

Deixe-me mostrar-lhe 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 vai olhar para o namespace global, já que não existe aqui. Então, a instrução IS_IDENTICAL executa a instrução IF.

Agora tente adicionar o backslash a uma constante:

PHP

 

Como você pode ver no opcode, o motor não precisa tentar buscar a constante porque agora é claro onde ela está e, sendo uma valor estática, já tem ela em memória.

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

Esta é a razão pela qual você tem muito poder para influenciar o desempenho final do seu código PHP.

Conclusão

Espero que o assunto tenha sido interessante. Como mencionei no início do artigo, estou obtendo muitos benefícios com o uso desta táctica e, de fato, elas também são usadas em nossos pacotes.

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

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

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