php-memprof é uma extensão de perfil de memória rápida e precisa para PHP que pode ser usada para encontrar a causa de vazamentos de memória.
A extensão rastreia a alocação e liberação de blocos de memória para relatar a quantidade de memória vazada por cada função, método ou arquivo em um programa.
Reporta memória não liberada em pontos arbitrários do programa
Despeja o perfil nos formatos callgrind, pprof ou raw array
Pode rastrear a memória alocada pelo próprio PHP, bem como pelo malloc nativo
php-memprof depende de libjudy e sys/queue.h.
Nas distribuições baseadas em Debian as dependências podem ser instaladas com:
# Debian or Ubuntu: apt install libjudy-dev
No Alpino:
# Alpine apk add judy-dev bsd-compat-headers
No MacOS:
# install libjudy dependency: brew install traildb/judy/judy
Certifique-se de instalar dependências e então:
pecl install memprof
No MacOS: JUDY_DIR=$(brew --prefix traildb/judy/judy) pecl install memprof
Nota Se libjudy estiver instalado em um caminho não padrão (não /usr ou /usr/local), use o método de instalação manual abaixo.
Certifique-se de instalar dependências e então:
Baixe a fonte e execute os seguintes comandos no diretório de origem:
phpize ./configure make make install
Nota Se libjudy estiver instalado em um caminho não padrão (não /usr ou /usr/local), você poderá especificá-lo assim:
./configure --with-judy-dir=/opt/homebrew/Cellar/judy/1.0.5
Os usuários do Arch Linux podem preferir instalar o pacote não oficial php-memprof com makepkg
ou seu auxiliar AUR preferido. Se estiver usando yay
, por exemplo:
yay -S php-memprof
Por favor, relate quaisquer problemas com este pacote em sua página AUR.
A extensão pode ser carregada na linha de comando, apenas para um script:
php -dextension=memprof.so script.php
Ou permanentemente, no php.ini:
extension=memprof.so
A extensão não tem sobrecarga quando não está criando perfil, portanto pode ser carregada por padrão em ambientes de desenvolvimento.
A maneira mais simples de usar memprof
é permitir que ele salve o perfil de memória quando o limite de memória do programa for excedido.
dump_on_limit
A criação de perfil no modo dump_on_limit
é habilitada na inicialização da solicitação quando uma destas situações for verdadeira:
A variável de ambiente MEMPROF_PROFILE
é igual a dump_on_limit
$_GET["MEMPROF_PROFILE"]
é igual a dump_on_limit
$_POST["MEMPROF_PROFILE"]
é igual a dump_on_limit
Para scripts de linha de comando, podemos definir a variável de ambiente:
MEMPROF_PROFILE=dump_on_limit php test.php
Para scripts web, podemos definir a variável $_GET
:
curl http://127.0.0.1/test.php?MEMPROF_PROFILE=dump_on_limit
Ou a variável $_POST
:
curl -d MEMPROF_PROFILE=dump_on_limit http://127.0.0.1/test.php
Nota A função
memprof_enabled_flags()
pode ser chamada para verificar se a criação de perfil está atualmente habilitada no mododump_on_limit
.
Neste modo, memprof
salvará automaticamente o perfil se o programa exceder o limite de memória (quando o PHP dispara um erro como Fatal error: Allowed memory size of 15728640 bytes exhausted (tried to allocate 1024 bytes)
erro).
Por padrão, o perfil é salvo em um arquivo chamado memprof.callgrind.*
em /tmp
ou C:WindowsTemp
.
A forma recomendada de visualizar o resultado é usar Kcachegrind (no Linux) ou Qcachegrind (no MacOS, Windows). Google Perftools também são suportados. Consulte a documentação de memprof_dump_callgrind()
e variantes.
A maioria das distribuições possui um pacote kcachegrind
pronto para ser instalado.
Por exemplo, Ubuntu ou Debian:
sudo apt install kcachegrind
Outras distribuições provavelmente também possuem um pacote pronto para ser instalado.
Use Homebrew: https://formulae.brew.sh/formula/qcachegrind
Baixe-o em https://sourceforge.net/projects/qcachegrindwin/
A criação de perfil é habilitada na inicialização da solicitação quando uma destas situações for verdadeira:
A variável de ambiente MEMPROF_PROFILE
não está vazia
$_GET["MEMPROF_PROFILE"]
não está vazio
$_POST["MEMPROF_PROFILE"]
não está vazio
A variável MEMPROF_PROFILE
aceita uma lista de sinalizadores separados por vírgula.
Exemplos de valores MEMPROF_PROFILE
válidos:
1
: não vazio: o perfil está habilitado
dump_on_limit
: o perfil está habilitado, despejará no limite de memória
native
: a criação de perfil está habilitada, criará perfil de alocações nativas
dump_on_limit,native
: a criação de perfil está habilitada, criará perfil de alocações nativas, despejará no limite de memória
Lista de sinalizadores válidos:
dump_on_limit
: irá despejar o perfil no formato callgrind em /tmp
ou C:WindowsTemp
. O diretório de saída pode ser alterado com a configuração memprof.output_dir
ini.
native
: criará o perfil das alocações nativas malloc()
, não apenas do PHP (isso não é seguro para threads, veja abaixo).
O Memprof não rastreia alocações nativas por padrão, mas isso pode ser habilitado definindo MEMPROF_PROFILE
como native
.
Alocações nativas são as alocações feitas fora do alocador de memória do próprio PHP. Normalmente, bibliotecas externas como libxml2 (usada na extensão DOM) fazem alocações nativas. PHP também pode fazer alocações nativas para recursos persistentes.
A ativação do rastreamento de alocação nativa criará um perfil dessas alocações, além das próprias alocações do PHP.
Observe que quando o rastreamento nativo está habilitado, o programa irá travar se uma biblioteca nativa usar threads, porque os ganchos subjacentes não são thread-safe.
O formato do arquivo de saída é definido com a configuração memprof.output_format
ini. As opções são:
callgrind
(padrão)
pprof
Nota : isso pode estar disponível apenas quando a extensão é compilada a partir do código-fonte (e não instalada com pecl), a partir do nº 101.
Retorna se o perfil de memória está habilitado no momento (veja acima).
Retorna se o perfil de memória e quais recursos de perfil estão habilitados (veja acima).
Despeja o perfil atual no formato callgrind. O resultado pode ser visualizado com ferramentas como KCacheGrind ou QCacheGrind.
<phpmemprof_dump_callgrind(fopen("saída", "w"));
Aqui está uma captura de tela do QcacheGrind:
Despeja o perfil atual no formato pprof.
<?phpmemprof_dump_pprof(fopen("profile.heap", "w"));
O arquivo pode ser visualizado com a ferramenta pprof
do google-perftools. (Veja abaixo as instruções de instalação.)
Exibir gráfico de chamadas anotado no navegador da web ou em gv
:
$ pprof --web profile.heap $ # or: $ pprof --gv profile.heap
Produza uma linha por função, classificada pelo próprio uso de memória:
$ pprof --text profile.heap
pprof
: Ubuntu: apt install google-perftools
. No Ubuntu, a ferramenta se chama google-pprof
, então você precisa substituir pprof
por google-pprof
nos exemplos acima.
Retorna uma matriz que representa o perfil atual.
<php$dump = memprof_dump_array();
A matriz expõe as seguintes informações:
Memória inclusiva e exclusiva vazada por funções (contando apenas a memória que ainda não foi liberada quando memprof_dump_array é chamado)
Contagem de blocos inclusivos e exclusivos de funções (número de alocações; contando apenas os blocos que ainda não foram liberados quando memprof_dump_array é chamado)
Os dados são apresentados em pilhas de chamadas. Dessa forma, se uma função for chamada de vários locais, é possível ver qual caminho de chamada causou maior vazamento de memória
Array ( [memory_size] => 11578 [blocks_count] => 236 [memory_size_inclusive] => 10497691 [blocks_count_inclusive] => 244 [calls] => 1 [called_functions] => Array ( [main] => Array ( [memory_size] => 288 [blocks_count] => 3 [memory_size_inclusive] => 10486113 [blocks_count_inclusive] => 8 [calls] => 1 [called_functions] => Array ( [a] => Array ( [memory_size] => 4 [blocks_count] => 1 [memory_size_inclusive] => 10485825 [blocks_count_inclusive] => 5 [calls] => 1 [called_functions] => Array ( [b] => Array ( [memory_size] => 10485821 [blocks_count] => 4 [memory_size_inclusive] => 10485821 [blocks_count_inclusive] => 4 [calls] => 1 [called_functions] => Array ( [str_repeat] => Array ( [memory_size] => 0 [blocks_count] => 0 [memory_size_inclusive] => 0 [blocks_count_inclusive] => 0 [calls] => 1 [called_functions] => Array ( ) ) ) ) ) ) [memprof_dump_array] => Array ( [memory_size] => 0 [blocks_count] => 0 [memory_size_inclusive] => 0 [blocks_count_inclusive] => 0 [calls] => 1 [called_functions] => Array ( ) ) ) ) ) )
Retorna a versão da extensão como uma string. A versão pode ser comparada com version_compare().
As extensões podem entrar em conflito com xdebug, blackfire ou outras extensões. Se esse for o seu caso, por favor denuncie.
O branch atual suporta PHP 7.1 a PHP 8.
A ramificação php5 suporta PHP 5.
Veja INTERNALS.md