...

PHP OPcache explicado em profundidade: como tirar o máximo partido da sua cache

O PHP OPcache acelera os meus scripts porque o PHP compila o bytecode na memória, poupando assim uma nova análise. Neste guia, mostro como utilizo o OPcache. configurar, monitorizo e ajusto com precisão para que a sua aplicação responda de forma significativamente mais rápida e absorva picos de carga com tranquilidade.

Pontos centrais

  • Cache de bytecode reduz a carga da CPU e a E/S
  • Parâmetros como selecionar especificamente memory_consumption e max_accelerated_files
  • Arredores ajustar de forma diferenciada: Dev, Staging, Produção
  • Monitorização para taxa de acertos, ocupação, evictions
  • Implantação e limpar o cache

Como funciona o OPcache: bytecode em vez de recompilação

Para cada solicitação, o PHP normalmente lê os ficheiros, analisa o código e cria bytecode, executado pelo Zend Engine. O OPcache atua exatamente aqui e armazena esse bytecode na memória partilhada, para que as solicitações subsequentes sejam iniciadas diretamente da memória. Isso reduz os ciclos da CPU e os acessos aos ficheiros, o que diminui significativamente os tempos de resposta. Em configurações típicas, consigo ganhos entre 30 e 70 por cento, dependendo da base de código e do perfil de tráfego. O importante é que o cache permaneça grande o suficiente e os scripts mais importantes fiquem permanentemente no Memória permanecer.

Verificar e ativar o OPcache no Linux, Windows e alojamento partilhado

Começo sempre por consultar o phpinfo() e procurar por „Zend». OPcache“ e chaves como opcache.enable ou opcache.memory_consumption. No Linux, ativo o módulo através do pacote php-opcache e um opcache.ini no diretório conf.d. No Windows, basta inserir zend_extension=opcache no php.ini e reiniciar o servidor web. Na hospedagem partilhada, ativo frequentemente o OPcache através de um php.ini personalizado ou através do menu do cliente. Em caso de congestionamentos, verifico também o Aumentar o limite de memória PHP, para que o OPcache e o PHP-FPM tenham recursos suficientes Recursos recebido.

Os interruptores mais importantes explicados de forma compreensível

Com opcache.enable, ativo a cache para solicitações da Web, enquanto opcache.enable_cli controla o uso para tarefas CLI, o que é útil para filas de trabalho. O núcleo é opcache.memory_consumption, que especifica a memória partilhada disponível em megabytes; uma estimativa muito baixa leva a evictions e novas compilações. opcache.max_accelerated_files define quantos ficheiros podem ser armazenados na cache; este valor deve exceder significativamente o número de ficheiros do projeto. Com opcache.validate_timestamps e opcache.revalidate_freq, determino o rigor com que o OPcache verifica as alterações nos ficheiros, desde muito dinâmico (desenvolvimento) até muito econômico (produção com flush manual). Salvo comentários com opcache.save_comments=1, porque muitas ferramentas em DocBlocks dependem.

Valores iniciais e perfis em comparação

Para uma introdução tranquila, aposto em perfis claros para desenvolvimento, staging e produção. Assim, obtenho ciclos de feedback rápidos durante a codificação e, por outro lado, um desempenho fiável em operação ao vivo. É importante que verifique regularmente esses valores iniciais em relação a métricas reais e os ajuste. Para instalações maiores do WordPress, planeio generosamente a memória e as entradas, porque os plugins e temas ocupam muito espaço. Arquivos gerar. A tabela seguinte resume valores iniciais úteis, que eu ajusto posteriormente com base na taxa de acertos e evictions.

Definição Desenvolvimento Preparação/Teste Produção
opcache.enable 1 1 1
opcache.enable_cli 0 0–1 1 (para tarefas CLI)
opcache.memory_consumption 128–256 MB 256–512 MB 256–512+ MB
opcache.interned_strings_buffer 16–32 MB 32–64 MB 16–64 MB
opcache.max_accelerated_files 8.000–10.000 10.000–20.000 10 000–20 000+
opcache.validate_timestamps 1 1 0–1 (dependendo da implementação)
opcache.revalidate_freq 0–2 s 60–300 s 300+ s ou 0 (com verificação manual)
opcache.save_comments 1 1 1
opcache.fast_shutdown 1 1 1

Esta matriz é deliberadamente pragmática, porque os projetos reais crescem de formas muito diferentes. Começo com estes valores e, em seguida, observo a taxa de acertos, a quota ocupada na memória partilhada e a ocorrência de evictions. Se houver sinais de pressão, primeiro aumento o opcache.memory_consumption em passos moderados. Em seguida, ajusto o opcache.max_accelerated_files até que o número de ficheiros caiba confortavelmente. Assim, o Cache eficaz e as consultas continuam a fluir uniformemente.

Configurações por ambiente: desenvolvimento, preparação, produção

No desenvolvimento, respostas rápidas às alterações de código são importantes, por isso defino validate_timestamps=1 e revalidate_freq muito baixo ou mesmo 0. No staging, verifico a carga realista e defino a memória generosamente, para que os resultados se aproximem da operação ao vivo posterior. Na produção, aumento a frequência de verificação ou desativo completamente os carimbos de data/hora, se a minha implementação esvaziar o cache de forma seletiva. Para trabalhadores baseados em CLI, ativo enable_cli=1, para que tarefas recorrentes também sejam executadas pelo Cache de bytecode beneficiar. Assim, cada ambiente gera exatamente o comportamento que eu preciso, sem surpresas nos tempos de resposta.

Configurações avançadas que muitas vezes fazem a diferença

Além dos parâmetros básicos, existem interruptores com os quais posso aumentar a estabilidade e a segurança e minimizar os efeitos secundários:

  • opcache.max_wasted_percentage: Define a partir de que nível de fragmentação o OPcache inicia uma reconstrução interna da memória. Em bases de código muito variáveis, reduzo ligeiramente o valor para ter menos memória „desperdiçada“.
  • opcache.force_restart_timeout: período em segundos após o qual o OPcache executa uma reinicialização forçada quando uma reinicialização está pendente, mas os processos ainda estão ativos. Isso evita estados de suspensão muito longos.
  • opcache.file_update_protection: janela de proteção em segundos, durante a qual os ficheiros recém-alterados não são imediatamente armazenados em cache. Isso ajuda a evitar ficheiros parcialmente gravados durante implementações ou em unidades de rede.
  • opcache.restrict_api: Restringe quais scripts podem chamar opcache_reset() e funções de estado. Em produção, defino isso de forma rigorosa, para que apenas pontos finais de administração tenham acesso.
  • opcache.blacklist_filename: ficheiro no qual mantenho padrões que são excluídos da cache (por exemplo, geradores altamente dinâmicos). Isso economiza espaço para scripts mais críticos.
  • opcache.validate_permission e opcache.validate_root: ativadas quando há vários utilizadores/chroots em jogo. Assim, o PHP impede que o código armazenado em cache de um contexto seja utilizado sem autorização noutro.
  • opcache.use_cwd e opcache.revalidate_path: controlo de como o OPcache identifica scripts quando os caminhos são integrados através de diferentes diretórios de trabalho/links simbólicos. Em links simbólicos de lançamento, testo estes valores especificamente para evitar caches duplicados.
  • opcache.cache_id: Quando vários hosts virtuais partilham o mesmo SHM (raro), eu separo os caches de forma clara através de um ID único.
  • opcache.optimization_level: Normalmente deixo no padrão. Apenas em casos extremos de depuração é que reduzo temporariamente as passagens de otimização.

Pré-carregamento: manter partes do código permanentemente na memória

Com o PHP 7.4+, posso carregar e ligar ficheiros centrais do framework ou do projeto ao iniciar o servidor através do opcache.preload e do opcache.preload_user. A vantagem: as classes estão disponíveis sem autoload hits e os hot paths estão imediatamente disponíveis. Algumas regras práticas:

  • O pré-carregamento vale a pena principalmente para bases de código grandes e estáveis (por exemplo, Symfony, bibliotecas principais próprias). No WordPress, eu o uso com cautela, porque o núcleo/plugins são atualizados com mais frequência.
  • Um ficheiro de pré-carregamento contém chamadas opcache_compile_file() específicas ou integra um autoloader que define classes antecipadamente carrega.
  • Qualquer alteração no código de ficheiros relevantes para o pré-carregamento requer uma reinicialização do PHP-FPM para que o pré-carregamento seja reconstruído. Eu integro isso nas implementações.
  • Eu avalio o efeito separadamente: nem todos os códigos se beneficiam; o pré-carregamento consome memória partilhada adicional.

JIT e OPcache: vantagens, limitações, requisitos de memória

Desde o PHP 8, existe o compilador Just-In-Time (JIT), que é controlado pelo OPcache (opcache.jit, opcache.jit_buffer_size). Para cargas de trabalho típicas da Web com carga de E/S e banco de dados, o JIT geralmente traz poucos benefícios. No entanto, ele pode ajudar significativamente em códigos com alta carga de CPU (por exemplo, processamento de imagens/dados). Eu procedo da seguinte forma:

  • Eu ativo o JIT de forma conservadora e meço métricas de utilizadores reais, bem como perfis de CPU. A ativação cega aumenta a necessidade de memória e pode desencadear casos extremos.
  • Eu dimensiono o buffer JIT dependendo das rotas com carga elevada da CPU. Buffers muito pequenos não agregam valor, enquanto buffers muito grandes substituem o bytecode.
  • Se a taxa de acertos ou a ocupação SHM forem afetadas, eu priorizo o OPcache em vez do JIT. O cache de bytecode é a alavanca mais importante para a maioria dos sites.

Caminhos de ficheiros, links simbólicos e estratégias de implementação seguras

O OPcache é baseado em caminho. Por isso, coloco a estratégia de implementação em destaque:

  • Lançamentos atómicos por symlink (por exemplo, /releases/123 -> /current): Limpo, mas atenção ao opcache.use_cwd e ao comportamento do realpath. Evito caches duplicados fazendo com que todos os trabalhadores vejam consistentemente o mesmo caminho real.
  • Com validate_timestamps=0, o cache deve em todo o lado Esvaziar: após a mudança, eu faço o flush do OPcache de forma direcionada em todos os hosts/pods e reinicio o PHP-FPM de forma controlada.
  • Eu coordeno realpath_cache_size e realpath_cache_ttl com OPcache para que as pesquisas de ficheiros permaneçam rápidas e estáveis.
  • Em unidades de rede (NFS/SMB), aumento o file_update_protection e configuro as implementações de forma a que os ficheiros sejam substituídos atomicamente.

Para reinicializações muito rápidas, costumo usar um procedimento em duas etapas: primeiro, aquecimento em segundo plano; depois, recarregamento rápido e coordenado de todos os trabalhadores, para que o primeiro tráfego ao vivo já encontre o cache aquecido.

Cache de ficheiros, aquecimento e preparação

Além da memória partilhada, o OPcache pode, opcionalmente, gravar o bytecode no disco (opcache.file_cache). Isso ajuda em cenários específicos:

  • Em ambientes de contentores, um cache de ficheiros pode entre Reinicializações FPM Reduzir os tempos de recompilação, desde que o armazenamento seja rápido.
  • Eu uso o opcache.file_cache com cautela: em sistemas de ficheiros lentos ou distribuídos, ele traz poucos benefícios e aumenta a complexidade.
  • opcache.file_cache_only é um caso especial para ambientes sem SHM – incomum para configurações de desempenho.

Para os aquecimentos, eu crio pequenos „primers“:

  • Um script CLI chama opcache_compile_file() para ficheiros quentes, por exemplo, autoloader, classes centrais do framework, grandes auxiliares.
  • Um rastreador visita as principais rotas (página inicial, login, checkout) para que o bytecode e os caches a jusante estejam aquecidos a tempo.
  • Eu programo os aquecimentos para que terminem pouco antes da mudança de versão.

OPcache na pilha: PHP-FPM, cache de objetos e cache de páginas

O OPcache mostra a sua força principalmente em combinação com o PHP-FPM, uma configuração de processo limpa e camadas de cache adicionais. No WordPress, eu o combino com um cache de objetos (como o Redis) e um cache de páginas, para aliviar a carga do banco de dados e da renderização. Para isso, presto atenção ao Desempenho de thread único, porque as solicitações PHP dependem muito dos núcleos individuais da CPU. Se, mesmo assim, houver pressão, distribuo a carga pelos PHP-FPM-Worker, sem selecionar uma memória partilhada do OPcache muito pequena. Assim, utilizo o Pilha completo, em vez de apenas ajustar um parafuso.

Erros frequentes e controlos rápidos

Um cache muito pequeno leva a evictions, que eu reconheço no status do OPcache ou phpinfo(). Se isso acontecer, eu aumento gradualmente o opcache.memory_consumption e controlo o efeito através da taxa de acertos. Se os ficheiros continuarem sem aceleração, eu defino o opcache.max_accelerated_files para um valor superior à quantidade real de ficheiros no projeto. Em caso de problemas de implementação, verifico validate_timestamps: com 0, o bytecode antigo permanece ativo até eu esvaziar explicitamente a cache. Ferramentas como Doctrine exigem DocBlocks, por isso deixo save_comments=1 para Erro evitar a falta de anotações.

Monitorizar e interpretar o OPcache

Eu meço a taxa de acertos e busco valores próximos a 100% de forma contínua, para que as consultas quase sempre sejam iniciadas a partir do cache. Além disso, observo a utilização da memória e o número de evictions para detetar atempadamente eventuais estrangulamentos. Com opcache_get_status(), crio pequenos painéis de controlo ou alimento soluções de monitorização existentes. Assim, vejo imediatamente as alterações após lançamentos ou atualizações de plugins. Com estas métricas, tomo decisões fundamentadas. Decisões e adapte apenas o que for realmente necessário.

Diretrizes concretas que se mostraram eficazes:

  • Taxa de acertos > 99 % sob carga normal e pico; abaixo disso, verifico a distribuição de ficheiros e o aquecimento.
  • Proporção livre de SHM constante > 5–10 %; caso contrário, eu escalo a memória.
  • Evictions ao longo do tempo: picos pontuais após a implementação são aceitáveis; evictions contínuas indicam subdimensionamento ou forte fragmentação.
  • Ficar atento à memória desperdiçada: se ela atingir o limite, planeio uma recriação controlada do OPcache (por exemplo, em janelas de manutenção).

Exemplo: configuração do WordPress com tráfego elevado

Para grandes sites WordPress, eu seleciono opcache.enable=1 e opcache.enable_cli=1, para que os CLI-Workers também se beneficiem. Eu gosto de definir a memória partilhada para 384 MB ou mais, quando há muitos plugins e um tema rico em funcionalidades envolvidos. Aumento o opcache.interned_strings_buffer para 64 MB, porque muitos nomes de classes e funções se repetem em todas as solicitações. Para ambientes de desempenho extremo, defino validate_timestamps=0 e revalidate_freq=0, mas limpo o cache imediatamente após cada lançamento. É importante projetar as implementações de forma que nenhum antigo bytecode continua em circulação.

Fluxo de trabalho prático para ajustes e implementações

Eu trabalho em ciclos fixos: medir, alterar, controlar. Primeiro, eu salvo valores de status como taxa de acertos, ocupação e evictions, depois ajusto um parâmetro e medo novamente. Antes de um lançamento, apago o OPcache de forma seletiva com os carimbos de data/hora desativados, seja através do reinício do PHP-FPM ou de um pequeno script. Em seguida, controlo os picos de carga com tráfego real ou benchmarks representativos. Se ocorrer algum comportamento anormal, também verifico Fragmentação da memória, porque eles utilizam o Partilhado A memória diminui.

Algumas rotinas adicionais que se mostraram eficazes em equipas:

  • Versões das alterações de parâmetros: opcache.ini no repositório, alterações por pull request e changelog.
  • Canary-Deploys: primeiro, apenas uma parte dos trabalhadores/pods carrega novas versões e cria cache, depois é feita a implementação em todas as instâncias.
  • Botão de emergência: um ponto final administrativo interno com acesso seguro que permite opcache_reset() e chamadas opcache_invalidate() específicas – combinado com opcache.restrict_api.
  • Estimar a ordem de grandeza: como regra geral, calculo inicialmente 1–2 MB de OPcache por 100–200 ficheiros PHP e, em seguida, ajusto com base nas métricas reais. Para o WordPress com muitos plugins, adiciono buffer.

Brevemente resumido

O OPcache torna as aplicações PHP mais rápidas, compilando o bytecode na RAM. Com as configurações adequadas para memória, número de ficheiros e estratégia de carimbo de data/hora, você alcançará tempos de resposta consistentemente curtos. Certifique-se de que tudo esteja sincronizado com o PHP-FPM e outras camadas de cache, para que toda a pilha funcione perfeitamente em conjunto. Monitore a taxa de acertos, ocupação e evictions para fazer ajustes específicos. Assim, você garante um desempenho confiável e de alto nível. Plataforma para cargas elevadas e crescimento.

Artigos actuais