Preloading

A partir do PHP 7.4.0, o PHP pode ser configurado para pré-carregar scripts no opcache quando o mecanismo é iniciado. Quaisquer funções, classes, interfaces ou traits (mas não constantes) nestes arquivos ficarão globalmente disponíveis para todas as solicitações sem precisar ser incluídas explicitamente. Isso troca conveniência e desempenho (porque o código está sempre disponível) para uso de memória de linha de base. Também requer a reinicialização do processo PHP para limpar os scripts pré-carregados, o que significa que esse recurso é prático apenas para uso em produção, não em um ambiente de desenvolvimento.

Observe que a compensação ideal entre desempenho e memória pode variar de acordo com o aplicativo. "Pré-carregar tudo" pode ser a estratégia mais fácil, mas não necessariamente a melhor estratégia. Além disso, o pré-carregamento só é útil quando há um processo persistente de uma solicitação para outra. Isso significa que, embora possa funcionar em um script CLI se o opcache estiver ativado, geralmente é inútil. A exceção é ao usar o pré-carregamento em bibliotecas FFI.

Nota:

O pré-carregamento não é suportado no Windows.

A configuração do pré-carregamento envolve duas etapas e requer que o opcache esteja ativado. Primeiro, defina o valor opcache.preload em php.ini:

opcache.preload=preload.php

preload.php é um arquivo arbitrário que será executado uma vez na inicialização do servidor (PHP-FPM, mod_php, etc.) e carregará o código na memória persistente. Em servidores que iniciam como root antes de alternar para um usuário de sistema sem privilégios, ou se o PHP for executado como root (não recomendado), o valor opcache.preload_user pode especificar o usuário do sistema para executar o pré-carregamento. A execução do pré-carregamento como root não é permitida por padrão. Configure opcache.preload_user=root para permiti-lo explicitamente.

No script preload.php, qualquer arquivo referenciado por include, include_once, require, require_once ou opcache_compile_file() será analisado na memória persistente. No exemplo a seguir, todos os arquivos .php no diretório src serão pré-carregados, a menos que sejam um arquivo Test.

<?php
$directory
= new RecursiveDirectoryIterator(__DIR__ . '/src');
$fullTree = new RecursiveIteratorIterator($directory);
$phpFiles = new RegexIterator($fullTree, '/.+((?<!Test)+\.php$)/i', RecursiveRegexIterator::GET_MATCH);

foreach (
$phpFiles as $key => $file) {
require_once
$file[0];
}
?>

Ambos include e opcache_compile_file()> funcionarão, mas têm implicações diferentes sobre como o código é tratado.

  • include executará o código no arquivo, enquanto opcache_compile_file() não. Isso significa que apenas o primeiro suporta declaração condicional (funções declaradas dentro de um bloco if).
  • Como includeexecutará o código, os arquivos includes aninhados também serão analisados e suas declarações pré-carregadas.
  • opcache_compile_file() pode carregar arquivos em qualquer ordem. Ou seja, se a.php define a classe A e b.php define a classe B que estende A, então opcache_compile_file() pode carregar esses dois arquivos em qualquer ordem. Ao usar include, no entanto, a.php deve ser incluído primeiro.
  • Em ambos os casos, se um script posterior incluir um arquivo que já foi pré-carregado, seu conteúdo ainda será executado, mas quaisquer símbolos que ele definir não serão redefinidos. O uso de include_once não impedirá que o arquivo seja incluído uma segunda vez. Pode ser necessário carregar um arquivo novamente para incluir as constantes globais definidas nele, pois elas não são tratadas pelo pré-carregamento.
Qual abordagem é melhor, portanto, depende do comportamento desejado. Com código que, de outra forma, usaria um autoloader, opcache_compile_file() permite maior flexibilidade. Com o código que seria carregado manualmente, include será mais robusta.

add a note

User Contributed Notes 2 notes

up
2
postmaster at greg0ire dot fr
1 year ago
There are caveats when enabling preloading, one of them being that it should be enabled via a php.ini file. Enabling it with a php-fpm pool configuration won't work, for instance, since preloading is global and not per-pool. To make sure that you successfully enabled preloading, you should check for a preload_statistics key in the output of opcache_get_status(). There should already be an opcache_statistics key, but that's something else entirely.
up
1
postmaster at greg0ire dot fr
1 year ago
PHP 8.1 comes with an inheritance cache that partially overlaps with what the preloading already does. If you enabled preloading on lower versions then migrated to PHP 8.1, you might want to turn off preloading and see if that comes with a performance penalty or not.
To Top