OPcache
O OPcache melhora o desempenho do PHP armazenando o código pré-compilado na memória compartilhada, evitando ler e recompilar a cada requisição, o que economiza o uso de CPU e permite ao servidor processar muito mais acessos simultâneos.
Este tutorial mostra como verificar, ativar, configurar e validar o OPcache em um servidor de produção.
Pré-requisitos
- Acesso
rootousudoao servidor - PHP 7.0 ou superior (a partir do PHP 5.5 a extensão já vem junto com o PHP; no PHP 8.x ela é parte do núcleo)
- Saber qual SAPI você usa: PHP-FPM (Nginx/Apache) ou mod_php (Apache)
Passo 1: Verificar se o OPcache já está ativo
php -v
Se a saída mencionar with Zend OPcache, a extensão está instalada. Para confirmar se está habilitada:
php -i | grep -i "opcache.enable"
Passo 2: Instalar a extensão (se necessário)
Debian/Ubuntu
sudo apt update
sudo apt install php8.5-opcache
RHEL/Rocky/AlmaLinux (repositório Remi)
sudo dnf install php-opcache
Substitua 8.3 pela versão do PHP que você utiliza.
Passo 3: Localizar o arquivo de configuração
php --ini
Locais comuns:
| Distribuição | Caminho (FPM) |
|---|---|
| Debian/Ubuntu | /etc/php/8.3/fpm/conf.d/10-opcache.ini |
| RHEL/Rocky | /etc/php.d/10-opcache.ini |
Dica: em vez de editar o arquivo padrão (que pode ser sobrescrito em atualizações), crie um arquivo próprio com prioridade maior, por exemplo 99-opcache-custom.ini na mesma pasta conf.d.
Passo 4: Configurar o OPcache para produção
Crie o arquivo:
sudo nano /etc/php/8.3/fpm/conf.d/99-opcache-custom.ini
Conteúdo recomendado:
[opcache]
; Ativa o OPcache
opcache.enable=1
opcache.enable_cli=0
; Memória reservada para o bytecode (em MB)
opcache.memory_consumption=256
; Memória para strings internadas (em MB)
opcache.interned_strings_buffer=16
; Número máximo de arquivos em cache.
; Deve ser maior que a quantidade de arquivos .php do projeto.
opcache.max_accelerated_files=20000
; PRODUÇÃO: não verificar se os arquivos mudaram
; (maior desempenho; exige limpar o cache a cada deploy)
opcache.validate_timestamps=0
; Só relevante se validate_timestamps=1 (intervalo em segundos)
opcache.revalidate_freq=0
; Evita o desperdício de memória
opcache.max_wasted_percentage=10
; Salva o caminho completo do arquivo no cache
opcache.use_cwd=1
Explicação dos principais parâmetros
| Diretiva | Valor | Motivo |
|---|---|---|
opcache.enable |
1 |
Liga o cache |
opcache.enable_cli |
0 |
Na CLI o cache não persiste entre execuções, então não ajuda (exceto em workers de longa duração) |
opcache.memory_consumption |
256 |
O padrão (128 MB) costuma ser curto para projetos grandes |
opcache.max_accelerated_files |
20000 |
Use um valor acima do total de arquivos PHP (inclua o vendor/) |
opcache.validate_timestamps |
0 |
Elimina chamadas stat() a cada requisição, mas exige reset do cache no deploy |
Para contar quantos arquivos PHP seu projeto tem:
find /var/www/meuapp -type f -name "*.php" | wc -l
Passo 5 (opcional): Preload (PHP 7.4+)
O opcache.preload= executa um arquivo arbitrário que é executado uma única vez apenas na inicialização do servidor (PHP-FPM, mod_php, etc) na memória persistente, podendo ser muito útil no framework.
O Inphinit já fornece um script para tal uso, localizado em system/boot/preload.php que pode ser editado manualmente para configurar as classes mais usadas em sua aplicação, e para usa-lo, basta apontar sua localização como no exemplo:
opcache.preload=/path/to/my-app/system/boot/preload.php
opcache.preload_user=www-data
Se tiver alguma classe de muito uso, como uma classe instalada via composer, você pode editar, adicionando ao system/boot/preload.php, como no exemplo:
OPcache::preload(array(
...,
Foo\Bar\Baz::class,
));
Após modificar o arquivo é necessário reiniciar PHP-FPM.
Passo 6: Reiniciar o serviço e validar
Teste a configuração antes de reiniciar:
sudo php-fpm8.5 -t
Reinicie:
sudo systemctl restart php8.5-fpm
Se usar estiver usando Apache com mod_php, o comando para reiniciar é:
sudo systemctl restart apache2
Passo 7: Limpar o cache a cada deploy
Com validate_timestamps=0, o cache precisa ser invalidado após cada deploy. Opções:
Opção A: Recarregar o PHP-FPM (a mais simples e confiável)
sudo systemctl reload php8.5-fpm
O reload é gracioso: os workers terminam as requisições em andamento antes de serem substituídos, sem derrubar o serviço.
Opção B: Chamar opcache_reset() via requisição web
Crie uma rota protegida (por exemplo, acessível só via localhost) e chame-a ao final do deploy:
$app->action('GET', '/opcache/reset', function () {
if (!in_array($_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'], true)) {
http_response_code(403);
} elseif (opcache_reset()) {
return 'OPcache limpo.';
}
return 'Falha ao limpar cache.';
});
curl -s http://127.0.0.1/opcache/reset
Solução de problemas
| Sintoma | Causa provável | Solução |
|---|---|---|
| Alterações no código não aparecem | validate_timestamps=0 sem reset |
Rode systemctl reload php8.5-fpm |
opcache_get_status() retorna false |
OPcache desativado no FPM | Confira opcache.enable=1 e o arquivo ini do FPM |
| Taxa de acerto baixa | Cache cheio | Aumente memory_consumption e max_accelerated_files |
| FPM não sobe após ativar preload | Erro no script de preload | Veja journalctl -u php8.5-fpm |