Zend OPcache: conceito, instalação e configuração, com os valores do php.ini e a desativação do JIT
O Zend OPcache é uma extensão do PHP que compila os scripts PHP em bytecode e os guarda na memória compartilhada, para que a compilação seja pulada quando o mesmo arquivo for executado de novo. Quando a ativação do JIT em um servidor WordPress com PHP 8.3 causou erro 500 em todas as páginas, o servidor foi recuperado mantendo o OPcache como estava e desativando apenas o JIT.
Desde o PHP 5.5, o OPcache já vem incluído no PHP por padrão.
1️⃣ Conceito do Zend OPcache: cache de bytecode
A cada requisição, um script PHP passa por três etapas: ler o arquivo, compilar em bytecode e executar. Com o OPcache em funcionamento, a partir da segunda requisição do mesmo arquivo as duas primeiras etapas somem e só a execução permanece.
A memória compartilhada em que o OPcache guarda o bytecode é usada em conjunto por todos os workers do PHP-FPM. Se vários sites estiverem ligados ao mesmo PHP-FPM, os scripts desses sites também são guardados em uma única memória compartilhada.
O que o OPcache guarda é código PHP compilado, então a execução do PHP e as consultas ao banco de dados continuam acontecendo toda vez que uma página é aberta. Pular a execução do PHP por completo guardando o HTML pronto é papel do cache de página.
2️⃣ Verificar a instalação do PHP OPcache
Para saber se o OPcache está instalado, veja a última linha da saída de [php -v].
php -vPHP 8.3.22 (cli) (built: Jun 3 2025 17:17:57) (NTS gcc x86_64)
Copyright (c) The PHP Group
Zend Engine v4.3.22, Copyright (c) Zend Technologies
with Zend OPcache v8.3.22, Copyright (c), by Zend TechnologiesSe a última linha não aparecer, instale com o dnf. O nome do pacote costuma ser php-opcache; se você instalou várias versões do PHP juntas pelo repositório Remi, a versão entra no nome, como em php83-php-opcache.
dnf -y install php-opcacheO pacote php-opcache do repositório Remi carrega a extensão pela linha [zend_extension=opcache] de [/etc/php.d/10-opcache.ini]. Depois de instalar, reinicie o PHP-FPM para que o OPcache também valha para as requisições web.
3️⃣ Configuração do OPcache: valores do php.ini
As configurações do OPcache podem ficar em dois lugares: na seção [opcache] de [/etc/php.ini] e em [/etc/php.d/10-opcache.ini].
php --iniConfiguration File (php.ini) Path: /etc
Loaded Configuration File: /etc/php.ini
Scan for additional .ini files in: /etc/php.d
Additional .ini files parsed: /etc/php.d/10-opcache.ini,Os arquivos da pasta php.d são lidos depois do php.ini; por isso, se a mesma diretiva estiver nos dois lugares, vale o valor do php.d.
A tabela abaixo mostra os valores padrão do PHP 8.3 e os valores aplicados no servidor WordPress que foi verificado.
| Item | Padrão do PHP 8.3 | Valor aplicado | Significado |
|---|---|---|---|
| opcache.enable | 1 | 1 | Ativa o OPcache |
| opcache.enable_cli | 0 | 1 | Também usado no PHP da linha de comando (wp-cli etc.) |
| opcache.memory_consumption | 128 | 1024 | Memória compartilhada que guarda o bytecode (MB) |
| opcache.interned_strings_buffer | 8 | 16 | Memória que guarda cada string idêntica uma única vez (MB) |
| opcache.max_accelerated_files | 10000 | 10000 | Limite máximo de chaves que podem ser colocadas em cache (o limite real é um número primo igual ou maior que esse valor: 16229 para 10000) |
| opcache.max_wasted_percentage | 5 | 10 | Se a memória acabar e o espaço desperdiçado passar dessa porcentagem, o cache é esvaziado e reiniciado |
| opcache.validate_timestamps | 1 | 1 | Verifica se os arquivos mudaram |
| opcache.revalidate_freq | 2 | 60 | Intervalo da verificação de mudanças nos arquivos (segundos) |
| opcache.jit | tracing | disable | Modo do JIT (a partir do PHP 8.4 o padrão é disable) |
| opcache.jit_buffer_size | 0 | 0 | Memória do JIT; com 0, o JIT não funciona (a partir do PHP 8.4 o padrão é 64M) |
Os valores colocados na seção [opcache] de [/etc/php.ini] estão abaixo. O tamanho da memória é definido conforme a memória do servidor, e [opcache.max_accelerated_files] conforme o número de arquivos do WordPress.
[opcache]
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=1024
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.max_wasted_percentage=10
opcache.validate_timestamps=1
opcache.revalidate_freq=60Se você colocar de novo uma linha [zend_extension] no php.ini, a extensão é carregada duas vezes e aparece o aviso [Cannot load Zend OPcache].
Com [opcache.revalidate_freq] em 60, depois de editar um arquivo PHP o código antigo pode continuar sendo executado por até 60 segundos.
Em um servidor WordPress em que os arquivos PHP mudam com frequência, deixe [opcache.validate_timestamps] em 1 para que as mudanças nos arquivos sejam verificadas. O 0 que a documentação do Symfony recomenda para servidores de produção serve para servidores em que os arquivos PHP só mudam quando uma nova versão é implantada.
Mesmo com [opcache.validate_timestamps] em 0, o próprio WordPress limpa o cache dos arquivos alterados quando você atualiza pela tela de administração. Mas, se você atualizar com o wp-cli ou editar arquivos por SSH, o código antigo continua sendo executado até o PHP-FPM ser reiniciado.
4️⃣ Desativar o JIT do OPcache
O JIT do PHP 8 acelera tarefas que exigem muito cálculo da CPU, então o efeito é pequeno em uma aplicação como o WordPress, que atende requisições web. Na medição com WordPress publicada no RFC do JIT do PHP, a execução com o JIT ativado atendeu 326 requisições por segundo e a execução com o JIT desativado, 315.
Em um servidor WordPress com PHP 8.3.22, o JIT foi ativado com [opcache.jit=tracing] e [opcache.jit_buffer_size=128M]. Três dias depois, em um dia em que uma enxurrada de requisições fez os workers do PHP-FPM reiniciarem várias vezes, ocorreu erro 500 em todas as páginas.
No registro de erros ficou a mensagem [Allowed memory size of 1073741824 bytes exhausted]. O [tried to allocate 4295229440 bytes] que vem depois é o registro de uma tentativa de alocar 4 GB de uma vez com um limite de memória do PHP de 1 GB. Depois que o JIT foi desativado, as mesmas requisições foram processadas normalmente.
O JIT é desativado colocando as duas linhas abaixo em [/etc/php.d/10-opcache.ini]. Mesmo que ainda haja configurações do JIT em [/etc/php.ini], valem os valores deste arquivo.
opcache.jit=disable
opcache.jit_buffer_size=0No PHP 8.3, o padrão de [opcache.jit_buffer_size] é 0; por isso, se você não configurar à parte, o JIT não funciona. A partir do PHP 8.4, o padrão de [opcache.jit] também é disable.
5️⃣ Aplicar e verificar a configuração
As configurações alteradas só passam a valer depois que o PHP-FPM é reiniciado.
systemctl restart php-fpmDepois de reiniciar, a memória compartilhada do OPcache é esvaziada e alocada de novo com as novas configurações.
php -i | grep -E '^opcache\.(enable|memory_consumption|revalidate_freq|validate_timestamps|jit) 'opcache.enable => On => On
opcache.jit => disable => disable
opcache.memory_consumption => 1024 => 1024
opcache.revalidate_freq => 60 => 60
opcache.validate_timestamps => On => OnOs valores exibidos por [php -i] são as configurações do PHP da linha de comando. Na família RHEL, o PHP-FPM lê os mesmos arquivos [/etc/php.ini] e [/etc/php.d], então os valores são iguais.
Se você chamar [opcache_get_status()] na linha de comando, aparecem 0 scripts em cache. O PHP da linha de comando cria uma memória compartilhada nova a cada execução; por isso, o uso do PHP-FPM é verificado colocando o arquivo abaixo na pasta de documentos web e abrindo-o no navegador.
<?php
header('Content-Type: text/plain');
$s = opcache_get_status(false);
print_r($s['memory_usage']);
print_r($s['opcache_statistics']);
print_r($s['interned_strings_usage']);
var_dump($s['cache_full']);Se [cache_full] for true, a memória compartilhada ou as chaves estão cheias. Depois de verificar, apague este arquivo imediatamente.
Em um servidor em que três sites WordPress usam o mesmo PHP-FPM, 317 MB dos 1024 MB de memória compartilhada estavam em uso. Havia de 3.366 a 4.222 scripts em cache por site, 11.358 no total.
O OPcache guarda os scripts pelo caminho real e, para arquivos carregados por um caminho relativo, cria mais uma chave com o diretório de trabalho anexado; por isso, o número de chaves fica maior que o de scripts. Com 11.358 scripts, as chaves encheram o limite de 16.229, e o buffer de strings de 16 MB também ficou sem espaço livre.
Quando as chaves enchem, os scripts novos não vão para o cache e são compilados a cada requisição. Em 5 minutos e 21 segundos, os cache misses subiram de 18.408 para 36.027, mas o número de scripts em cache permaneceu em 11.358.
Em um servidor que roda vários WordPress ou muitos plugins, defina [opcache.max_accelerated_files] com folga para que o limite de chaves não encha. Com 20000, o limite real de chaves passa a ser 32.531. Se o buffer de strings estiver cheio, aumente também [opcache.interned_strings_buffer].
🔢 FAQ & conteúdo recomendado
Cache
Cache: definição e todos os campos em que o cache é usado
Um artigo que organiza as áreas em que o cache é usado, incluindo o OPcache, que guarda código PHP compilado, e o cache de página, que guarda HTML pronto.
PHP-FPM
Aviso de max_children do php-fpm: descubra a causa nos logs antes de aumentar os workers
Um artigo sobre como descobrir pelos logs a causa do aviso que aparece quando todos os workers do PHP-FPM que compartilham a memória compartilhada do OPcache estão ocupados.
PHP-FPM
O que é PHP-FPM | Instalar e configurar o PHP-FPM
Um artigo sobre a instalação do PHP-FPM, dentro do qual o OPcache funciona, a configuração do pool no www.conf e a forma de reiniciá-lo.
ℹ️ Aviso de afiliados
O conteúdo deste site contém links de afiliados. Quando um visitante compra um produto ou serviço por meio de um desses links, o site recebe uma comissão do vendedor. O valor que o comprador paga (em promoções, ele diminui ↓) não aumenta por causa disso. Preços, descontos e informações de estoque valem para o momento em que o texto foi escrito e podem ter mudado, por isso confirme com o vendedor antes de comprar. Os produtos são escolhidos e avaliados por critérios próprios, e o recebimento de comissão não influencia a ordem de apresentação nem o conteúdo das avaliações.