Slide 1

Slide 1 text

Que bom que você tá aqui ❤ Senta que lá vem converseiro!

Slide 2

Slide 2 text

Tunando seu PHP em produção com cache de bytecode PHP 5 PHP 7 PHP 7/8 + CACHE

Slide 3

Slide 3 text

Renan H. Delmonico ➔ 27 anos ➔ Graduado em Sistemas de Informação (Unipar) ➔ Especialista em desenvolvimento web e mobile (Alfa Umuarama) ➔ Desenvolvedor há quase 10 anos ➔ Engenheiro de Software no PagSeguro Internacional (antigo BoaCompra) ➔ Apaixonado por futebol 🌴👍🌍 e esporte eletrônico (CS:GO) 🔫 @renandelmonico @renandelmonico /renandelmonico /renandelmonico /renandelmonico [email protected]

Slide 4

Slide 4 text

80% of performance issues have nothing to do with your server! Fonte: https://www.combell.com/en/performance-team

Slide 5

Slide 5 text

Conceitos do PHP ➔ Linguagem interpretada ➔ “Fire and forget” ◆ A cada request o PHP “compila” todos os arquivos que serão utilizados e depois executa as operações ➔ Não tem uma compilação “manual” ◆ Automágica 🧙 a cada request

Slide 6

Slide 6 text

99% das empresas não usam ou não sabem da existência do opcache Fonte: Times New Roman

Slide 7

Slide 7 text

PHP under the hood Redundante

Slide 8

Slide 8 text

PHP sem cache PHP bytecode RAM

Slide 9

Slide 9 text

Quem é o opcache? Nunca vi na fila do pão

Slide 10

Slide 10 text

Quem é o opcache? Nunca vi na fila do pão ➔ Melhora a performance do PHP armazenando o script em bytecode em memória RAM, removendo assim a necessidade de fazer a compilação a CADA request ➔ Sem o opcache todo o código compilado após a request é “descartado” sendo necessária a compilação novamente em uma nova requisição ➔ Em produção os opcodes não mudam ◆ A cada novo deploy é gerada uma nova imagem, com o novo código ➔ Existe desde o PHP 5.5 ➔ Zend Optimizer ◆ “doado” pela Zend

Slide 11

Slide 11 text

Zend Opcache Optimizer ➔ Várias funcionalidades, dentre elas ele remove o “código morto” ➔ Não são somente configurações, é possível fazer scripts para gerenciar o cache ➔ https://php.net/manual/en/ref.opcache.php

Slide 12

Slide 12 text

E o tal do preloading do PHP 7.4? ➔ Opcache com anabolizante ➔ Permite que você diga ao PHP FPM para gerar os opcodes e jogar no cache antes de executar qualquer código na Zend VM ➔ Zend VM? ◆ Depois dos opcodes gerados quem executa é a Zend VM ➔ ⚠ Não funciona no Windows ◆ Servidores em prod quase sempre são Linux! ➔ Depois disso ainda temos o JIT!

Slide 13

Slide 13 text

PHP 8 e o JIT ➔ Opcache faz com que a obtenção dos opcodes seja mais rápida para execução na Zend VM, o JIT faz com que os códigos sejam executados sem VM 🥰 ➔ Zend VM foi escrita em C e funciona como uma camada entre o opcode e o CPU, o JIT gera um código compilado em tempo de execução para que o PHP “pule” a Zend VM ➔ Implementação usa a lib DynASM (Dynamic Assembler) ◆ O JIT compiler transforma os opcodes em código de máquina específico da arquitetura da CPU usando o DynASM

Slide 14

Slide 14 text

Como o JIT se comporta? ➔ Compila apenas alguns opcodes que são mais utilizados ◆ Faz um profiling dos opcode executados e verifica quais faz sentido compilar ◆ Código do framework que estamos usando?

Slide 15

Slide 15 text

Beleza, mas como instalo e configuro esse tal de opcache?

Slide 16

Slide 16 text

E o bendito preloading?

Slide 17

Slide 17 text

Nossa, que fácil, pelo menos o JIT deve ser difícil né...

Slide 18

Slide 18 text

Agora vamos configurar essa bagaça ➔ Basicamente (existem outras, mas essa é a principal) essa é a única configuração que você irá alterar ➔ Cada posição desse número tem um significado ◆ É confuso? É. Mas é o que tem pra hoje ◆ De acordo com a lista do RFC, esse é o significado de cada número… ◆ A ordem das tabelas é da direita para esquerda

Slide 19

Slide 19 text

Agora vamos configurar essa bagaça O - Optimization Level 0 don’t JIT 1 minimal JIT (call standard VM handlers) 2 Inline VM handlers 3 Use type inference 4 use call graph 5 Optimize whole script

Slide 20

Slide 20 text

Agora vamos configurar essa bagaça T - Trigger 0 Compile all function on script load 1 Compile function on first execution 2 Profile functions on first request and compile the hottest functions afterwards 3 Profile on the fly and compile hot functions 4 Currently unused 5 Use tracing JIT. Profile on the fly and compile traces for hot code segments

Slide 21

Slide 21 text

Agora vamos configurar essa bagaça R - Register Allocation 0 Don’t perform register allocation 1 Perform block-local register allocation 2 Perform global register allocation

Slide 22

Slide 22 text

Agora vamos configurar essa bagaça C - CPU (specific optimization flags) 0 Disable CPU-specific optimization 1 Enable use of AVX, if the CPU supports it

Slide 23

Slide 23 text

Agora vamos configurar essa bagaça ➔ Reza a lenda que a melhor configuração é a 1255 ➔ A opção opcache.jit é opcional, se não informada será considerado o valor padrão ➔ E qual o valor padrão? ◆ opcache.jit=tracing ➔ Uai sô, mas não era aqueles numerozinhos marotos? ◆ Depois de aprovada a RFC, chegaram na conclusão que as opções não eram user-friendly, então refizeram tudo adicionaram dois alias que são “traduzidos” para os numerozinhos marotos. ● opcache.jit=tracing ● opcache.jit=function ➔ A diferença entre os dois é que function o JIT irá tentar otimizar somente o código dentro de um escopo de uma única função, enquanto o tracing faz o trace (ah, vá!) toda a pilha para identificar e otimizar o código. ➔ É recomendado o uso do trace, pois quase sempre apresentará resultados melhores

Slide 24

Slide 24 text

Mas a melhora dessa bagaça é significativa?

Slide 25

Slide 25 text

~60ms ~30ms 😱 <10ms

Slide 26

Slide 26 text

~39% ~13% 🐳🚫🧗

Slide 27

Slide 27 text

É isso! Perguntas ao vivo? Senão chama 🔥 no privado @renandelmonico @renandelmonico /renandelmonico /renandelmonico /renandelmonico [email protected]