PHP

3 jul, 2026

PHP além do Request-Response — Capítulo 1

Publicidade

Como o runtime do PHP evoluiu para suportar aplicações de alta concorrência

Durante mais de duas décadas, o PHP construiu sua reputação em torno de uma característica que, ao mesmo tempo, foi seu maior diferencial e sua maior limitação: a simplicidade do seu modelo de execução.

Enquanto outras linguagens exigiam servidores de aplicação complexos, gerenciamento explícito de memória e processos persistentes, o PHP seguia um caminho muito mais direto. Cada requisição HTTP era tratada como um evento completamente independente. O interpretador iniciava a execução do script, processava a lógica da aplicação, enviava a resposta ao cliente e descartava todo o estado criado durante aquele ciclo.

Esse modelo tornou o desenvolvimento Web incrivelmente acessível.

Também ajudou a consolidar o PHP como uma das linguagens mais utilizadas da Internet.

Segundo a W3Techs, ainda hoje mais de 70% dos sites cujo servidor é conhecido utilizam PHP em alguma camada da aplicação, impulsionados principalmente por plataformas como WordPress, Drupal, Magento e inúmeros sistemas corporativos desenvolvidos sob medida.

Entretanto, a própria arquitetura que tornou o PHP tão bem-sucedido passou a representar um desafio conforme as aplicações evoluíram.

Nos anos 2000, era comum que uma página consultasse apenas um banco de dados e retornasse o HTML ao navegador.

Em 2026, uma única requisição pode depender de dezenas de componentes distribuídos.

Um gateway de APIs pode precisar consultar simultaneamente:

  • PostgreSQL;
  • Redis;
  • Elasticsearch;
  • Kafka;
  • serviços internos;
  • APIs de terceiros;
  • provedores de autenticação;
  • sistemas de pagamento;
  • mecanismos de recomendação baseados em IA.

Nesse cenário, o gargalo deixou de ser a capacidade de processamento da CPU.

O verdadeiro problema passou a ser o tempo gasto aguardando respostas de outros sistemas.

E foi exatamente esse contexto que impulsionou uma das maiores mudanças já realizadas no runtime do PHP.

Antes de entendermos como Fibers, ReactPHP e Amp resolveram parte desse problema, precisamos voltar alguns passos e compreender como o PHP realmente executa uma requisição.

Essa jornada começa muito antes do primeiro echo.

Muito além do index.php

Quando um navegador envia uma requisição para uma aplicação PHP, existe uma cadeia relativamente longa de componentes trabalhando antes que o primeiro byte do código da aplicação seja executado.

Uma visão simplificada desse fluxo pode ser representada da seguinte forma:

                     Cliente HTTP
                          │
                          ▼
                 Nginx ou Apache
                          │
                          ▼
                      PHP-FPM
                          │
                          ▼
                 Worker disponível
                          │
                          ▼
              Inicialização do Runtime
                          │
                          ▼
                Zend Engine interpreta
                          │
                          ▼
               Composer Autoload
                          │
                          ▼
                Framework (Laravel,
                  Symfony, etc.)
                          │
                          ▼
                 Código da aplicação
                          │
                          ▼
                 Geração da resposta
                          │
                          ▼
                  Encerramento do script
                          │
                          ▼
                Liberação da memória

Observe que existe um detalhe extremamente importante nesse fluxo.

Ao final da requisição, praticamente tudo desaparece.

Objetos são destruídos.

Variáveis deixam de existir.

Conexões são encerradas.

O coletor de lixo libera a memória utilizada.

Na próxima requisição, todo esse processo será executado novamente.

Esse comportamento é completamente diferente do que acontece em runtimes persistentes como Node.js, Java, .NET ou Go.

Nessas plataformas, a aplicação permanece carregada durante horas ou até meses.

No PHP tradicional, a aplicação “nasce” e “morre” milhares de vezes por minuto.

O papel do Zend Engine

Existe um equívoco bastante comum entre desenvolvedores experientes.

Muitos acreditam que o PHP simplesmente interpreta arquivos .php linha por linha.

Na prática, o processo é significativamente mais sofisticado.

O núcleo da linguagem é o Zend Engine, responsável por transformar o código-fonte em instruções executáveis.

De maneira simplificada, o fluxo interno funciona assim:

Código PHP

        │

        ▼

Lexer (tokenização)

        │

        ▼

Parser

        │

        ▼

Árvore Sintática (AST)

        │

        ▼

Compilação para Opcodes

        │

        ▼

Máquina Virtual do Zend Engine

        │

        ▼

Execução

Cada arquivo PHP passa inicialmente por um processo de análise léxica, no qual o código é dividido em tokens.

Depois disso, o parser organiza esses elementos em uma Árvore Sintática Abstrata (AST), representando a estrutura lógica do programa.

Somente então ocorre a geração dos Opcodes, uma espécie de linguagem intermediária executada pela máquina virtual do Zend Engine.

Esse detalhe é importante porque desmonta um mito antigo.

O PHP não interpreta diretamente o código escrito pelo desenvolvedor.

Ele executa uma sequência de instruções intermediárias geradas durante o processo de compilação.

Onde o OpCache entra nessa história?

Se cada requisição recompilasse todos os arquivos da aplicação, o desperdício de processamento seria enorme.

Foi justamente para evitar isso que surgiu o OpCache.

Seu funcionamento é relativamente simples.

Na primeira execução, o Zend Engine gera os Opcodes normalmente.

Em vez de descartá-los ao final da requisição, o OpCache os mantém em memória compartilhada.

Nas requisições seguintes, o processo pode reutilizar esses Opcodes sem repetir toda a etapa de compilação.

O fluxo passa a ser o seguinte:

Primeira requisição

Código PHP
      │
      ▼
Compilação
      │
      ▼
Opcodes
      │
      ▼
OpCache
      │
      ▼
Execução


Requisições seguintes

Código PHP
      │
      ▼
OpCache
      │
      ▼
Execução

Esse mecanismo reduziu drasticamente o custo de inicialização das aplicações PHP.

Mais recentemente, o PHP também incorporou um compilador JIT (Just-in-Time), capaz de converter determinados trechos de Opcodes em código de máquina nativo durante a execução.

Embora o JIT tenha trazido ganhos relevantes para aplicações com processamento intensivo — como algoritmos matemáticos, processamento de imagens e computação científica — seu impacto em aplicações Web tradicionais costuma ser pequeno.

O motivo é simples.

Na maioria dos sistemas corporativos, o tempo não é consumido executando cálculos complexos.

O tempo é consumido esperando.

Esperando o banco de dados.

Esperando outra API.

Esperando um cache distribuído.

Esperando um serviço externo responder.

Esse detalhe muda completamente a forma como devemos pensar sobre desempenho.

PHP-FPM: muito mais do que um simples executor de scripts

Quando falamos em aplicações PHP modernas, quase sempre existe um componente silencioso desempenhando um papel fundamental: o PHP-FPM (FastCGI Process Manager).

Apesar de ser frequentemente tratado apenas como “o processo que executa o PHP”, sua responsabilidade é bem maior.

Ele gerencia um conjunto de workers, responsáveis por atender às requisições recebidas pelo servidor Web.

Sua arquitetura pode ser representada da seguinte maneira:

                   PHP-FPM Master
                          │
      ┌───────────────────┼───────────────────┐
      │                   │                   │
      ▼                   ▼                   ▼
 Worker 1            Worker 2            Worker 3
      │                   │                   │
Atende Request A    Atende Request B    Livre

O processo Master nunca executa código da aplicação.

Sua função é administrar o ciclo de vida dos processos filhos.

Entre suas responsabilidades estão:

  • criar novos workers;
  • encerrar processos inativos;
  • reiniciar workers com falha;
  • distribuir requisições;
  • controlar limites de memória;
  • monitorar consumo de recursos.

Já os workers executam efetivamente o código PHP.

Cada worker atende apenas uma requisição por vez.

Esse detalhe parece pequeno.

Mas ele explica praticamente todas as limitações do modelo tradicional do PHP.

Imagine que um worker receba uma requisição responsável por consultar cinco APIs externas.

Enquanto aguarda a resposta da primeira API, ele não poderá atender nenhuma outra requisição.

A CPU permanece praticamente ociosa.

O worker fica bloqueado.

Esse comportamento é conhecido como I/O bloqueante.

E é exatamente aqui que começa a próxima grande transformação do runtime do PHP.

No próximo capítulo, vamos abrir essa “caixa-preta” para entender por que aplicações modernas passam a maior parte do tempo esperando respostas externas, como o kernel do sistema operacional participa desse processo e por que a chegada das Fibers, no PHP 8.1, representou uma das mudanças arquiteturais mais importantes da história da linguagem.