php-memprof — это быстрое и точное расширение профилирования памяти для PHP, которое можно использовать для поиска причин утечек памяти.
Расширение отслеживает выделение и освобождение блоков памяти, чтобы сообщить об объеме памяти, утекшей каждой функцией, методом или файлом в программе.
Сообщает о несвободной памяти в произвольных точках программы.
Дамп профиля в форматах callgrind, pprof или необработанного массива.
Может отслеживать память, выделенную самим PHP, а также собственным malloc.
php-memprof зависит от libjudy и sys/queue.h.
В дистрибутивах на основе Debian зависимости можно установить с помощью:
# Debian or Ubuntu: apt install libjudy-dev
На Альпийском:
# Alpine apk add judy-dev bsd-compat-headers
В MacOS:
# install libjudy dependency: brew install traildb/judy/judy
Обязательно установите зависимости, а затем:
pecl install memprof
В MacOS: JUDY_DIR=$(brew --prefix Traildb/judy/judy) pecl install memprof
Примечание. Если libjudy установлена по нестандартному пути (не /usr или /usr/local), используйте метод ручной установки, указанный ниже.
Обязательно установите зависимости, а затем:
Загрузите исходный код и выполните следующие команды в исходном каталоге:
phpize ./configure make make install
Примечание. Если libjudy установлена по нестандартному пути (не /usr или /usr/local), вы можете указать его следующим образом:
./configure --with-judy-dir=/opt/homebrew/Cellar/judy/1.0.5
Пользователи Arch Linux могут предпочесть установить неофициальный пакет php-memprof с помощью makepkg или предпочитаемого ими помощника AUR. Если вы используете yay , например:
yay -S php-memprof
Пожалуйста, сообщайте о любых проблемах с этим пакетом на его странице AUR.
Расширение можно загрузить в командной строке всего для одного скрипта:
php -dextension=memprof.so script.php
Или навсегда в php.ini:
extension=memprof.so
Расширение не требует дополнительных затрат, когда оно не профилируется, поэтому его можно загружать по умолчанию в средах разработки.
Самый простой способ использовать memprof — позволить ему сохранять профиль памяти при превышении предела памяти программы.
dump_on_limit . Профилирование в режиме dump_on_limit включается при запуске запроса, если одно из следующих условий истинно:
Переменная среды MEMPROF_PROFILE равна dump_on_limit
$_GET["MEMPROF_PROFILE"] равен dump_on_limit
$_POST["MEMPROF_PROFILE"] равен dump_on_limit
Для сценариев командной строки мы можем установить переменную среды:
MEMPROF_PROFILE=dump_on_limit php test.php
Для веб-скриптов мы можем установить переменную $_GET :
curl http://127.0.0.1/test.php?MEMPROF_PROFILE=dump_on_limit
Или переменная $_POST :
curl -d MEMPROF_PROFILE=dump_on_limit http://127.0.0.1/test.php
Примечание. Функцию
memprof_enabled_flags()можно вызвать, чтобы проверить, включено ли в данный момент профилирование в режимеdump_on_limit.
В этом режиме memprof автоматически сохранит профиль, если программа превысит лимит памяти (когда PHP выдает ошибку типа Fatal error: Allowed memory size of 15728640 bytes exhausted (tried to allocate 1024 bytes) ).
По умолчанию профиль сохраняется в файле с именем memprof.callgrind.* в /tmp или C:WindowsTemp .
Рекомендуемый способ визуализации результата — использовать Kcachegrind (в Linux) или Qcachegrind (в MacOS, Windows). Google Perftools также поддерживаются. См. документацию memprof_dump_callgrind() и вариантов.
В большинстве дистрибутивов имеется готовый к установке пакет kcachegrind .
Например, Ubuntu или Debian:
sudo apt install kcachegrind
В других дистрибутивах, скорее всего, также есть пакет, готовый к установке.
Используйте Homebrew: https://formulae.brew.sh/formula/qcachegrind.
Загрузите его с https://sourceforge.net/projects/qcachegrindwin/.
Профилирование включается при запуске запроса, если выполняется одно из следующих условий:
Переменная среды MEMPROF_PROFILE не пуста.
$_GET["MEMPROF_PROFILE"] не пуст.
$_POST["MEMPROF_PROFILE"] не пуст.
Переменная MEMPROF_PROFILE принимает список флагов, разделенных запятыми.
Примеры допустимых значений MEMPROF_PROFILE :
1 : непусто: профилирование включено.
dump_on_limit : профилирование включено, дамп будет ограничен пределом памяти.
native : профилирование включено, будет профилироваться собственное распределение
dump_on_limit,native : профилирование включено, будет профилироваться собственное распределение, будет выгружаться по лимиту памяти.
Список допустимых флагов:
dump_on_limit : выгрузит профиль в формате callgrind в /tmp или C:WindowsTemp . Выходной каталог можно изменить с помощью ini-настройки memprof.output_dir .
native : будет профилировать собственные распределения malloc() , а не только PHP (это не потокобезопасно, см. ниже).
Memprof по умолчанию не отслеживает собственные выделения, но это можно включить, установив для MEMPROF_PROFILE native .
Собственные выделения — это выделения, выполняемые за пределами собственного распределителя памяти PHP. Обычно внешние библиотеки, такие как libxml2 (используемые в расширении DOM), выполняют собственное распределение. PHP также может самостоятельно выделять постоянные ресурсы.
Включение встроенного отслеживания выделения будет профилировать эти выделения в дополнение к собственным выделениям PHP.
Обратите внимание: когда встроенное отслеживание включено, программа выйдет из строя, если собственная библиотека использует потоки, поскольку базовые перехватчики не являются потокобезопасными.
Формат выходного файла определяется ini-настройкой memprof.output_format . Возможные варианты:
callgrind (по умолчанию)
pprof
Примечание . Это может быть доступно только в том случае, если расширение собрано из исходного кода (а не установлено с помощью pecl), начиная с #101.
Возвращает, включено ли в данный момент профилирование памяти (см. выше).
Возвращает, включено ли профилирование памяти и какие функции профилирования (см. выше).
Сбрасывает текущий профиль в формате callgrind. Результат можно визуализировать с помощью таких инструментов, как KCacheGrind или QCacheGrind.
<phpmemprof_dump_callgrind(fopen("выход", "w"));Вот скриншот QcacheGrind:
Сбрасывает текущий профиль в формате pprof.
<?phpmemprof_dump_pprof(fopen("profile.heap", "w")); Файл можно визуализировать с помощью инструмента pprof от google-perftools. (Инструкции по установке см. ниже.)
Отобразить аннотированный график вызовов в веб-браузере или в gv :
$ pprof --web profile.heap $ # or: $ pprof --gv profile.heap
Выведите по одной строке для каждой функции, отсортированной по использованию собственной памяти:
$ pprof --text profile.heap
pprof : Ubuntu: apt install google-perftools . В Ubuntu инструмент называется google-pprof , поэтому в приведенных выше примерах вам необходимо заменить pprof на google-pprof .
Возвращает массив, представляющий текущий профиль.
<php$dump = memprof_dump_array();
Массив предоставляет следующую информацию:
Инклюзивная и эксклюзивная память, утекшая из функций (считая только ту память, которая еще не освобождена при вызове memprof_dump_array)
Подсчет инклюзивных и эксклюзивных блоков функций (количество выделений; подсчет только тех блоков, которые еще не освобождены при вызове memprof_dump_array)
Данные представлены в стеках вызовов. Таким образом, если функция вызывается из нескольких мест, можно увидеть, какой путь вызова вызвал большую утечку памяти.
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 ( ) ) ) ) ) )
Возвращает версию расширения в виде строки. Версию можно сравнить с помощью version_compare().
Расширения могут конфликтовать с xdebug, blackfire или другими расширениями. Если это так, пожалуйста, сообщите об этом.
Текущая ветка поддерживает версии от PHP 7.1 до PHP 8.
Ветка php5 поддерживает PHP 5.
См. INTERNALS.md