• Stars
    star
    773
  • Rank 58,789 (Top 2 %)
  • Language
    C
  • License
    MIT License
  • Created almost 12 years ago
  • Updated about 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Memory profiler for PHP. Helps finding memory leaks in PHP scripts.

memprof logo

memprof

Supported PHP versions: 7.1 ... 8.x

php-memprof is a fast and accurate memory profiling extension for PHP that can be used to find the cause of memory leaks.

Features

The extension tracks the allocation and release of memory blocks to report the amount of memory leaked by every function, method, or file in a program.

  • Reports non-freed memory at arbitrary points in the program
  • Dumps profile in callgrind, pprof, or raw array formats
  • Can track memory allocated by PHP itself as well as native malloc

Install

Dependencies

php-memprof depends on libjudy. On Debian or Ubuntu, the dependency can be installed with:

# install libjudy dependency:
apt install libjudy-dev

On MacOS the dependency can be installed with:

# install libjudy dependency:
brew install traildb/judy/judy

Installing with PECL

Make sure to install dependencies, and then:

pecl install memprof

Note If libjudy is installed in a non-standard path (not /usr or /usr/local), please use the manual installation method bellow.

Installing manually

Make sure to install dependencies, and then:

Download the source and run the following commands in the source directory:

phpize
./configure
make
make install

Note If libjudy is installed in a non-standard path (not /usr or /usr/local), you can specify it like this:

./configure --with-judy-dir=/opt/homebrew/Cellar/judy/1.0.5

Installing on Arch Linux

Arch Linux users may prefer to install the unofficial php-memprof package with makepkg or their preferred AUR helper. If using yay, for example:

yay -S php-memprof

ℹ️ Please report any issues with this package on its AUR page.

Loading the extension

The extension can be loaded on the command line, just for one script:

php -dextension=memprof.so script.php

Or permanently, in php.ini:

extension=memprof.so

The extension has no overhead when not profiling, so it can be loaded by default on dev environments.

Usage example

The simplest way to use memprof is to let it save the memory profile when the program's memory limit is exceeded.

Step 1: Enable profiling in dump_on_limit mode

Profiling in dump_on_limit mode is enabled at request startup when one of these is true:

  • The environment variable MEMPROF_PROFILE is equal to dump_on_limit
  • $_GET["MEMPROF_PROFILE"] is equal to dump_on_limit
  • $_POST["MEMPROF_PROFILE"] is equal to dump_on_limit

For command line scripts, we can set the environment variable:

MEMPROF_PROFILE=dump_on_limit php test.php

For web scripts, we can set the $_GET variable:

curl http://127.0.0.1/test.php?MEMPROF_PROFILE=dump_on_limit

Or the $_POST variable:

curl -d MEMPROF_PROFILE=dump_on_limit http://127.0.0.1/test.php

Note The memprof_enabled_flags() function can be called to check whether profiling is currently enabled in dump_on_limit mode.

Step 2: Dumping the profile

In this mode, memprof will automatically save the profile if the program exceeds the memory limit (when PHP triggers an error like Fatal error: Allowed memory size of 15728640 bytes exhausted (tried to allocate 1024 bytes) error).

By default, the profile is saved in a file named memprof.callgrind.* in /tmp or C:\Windows\Temp.

Step 3: Visualizing the profile

The recommended way to visualize the result is to use Kcachegrind (on Linux) or Qcachegrind (on MacOS, Windows). Google Perftools are also supported. See the documentation of memprof_dump_callgrind() and variants.

Install Kcachegrind on Linux

Most distributions have a kcachegrind package ready to be installed.

For example, Ubuntu or Debian:

sudo apt install kcachegrind

Other distributions most likely have a package ready to be installed as well.

Install Qcachegrind on MacOS

Use Homebrew: https://formulae.brew.sh/formula/qcachegrind

Install Qcachegrind on Windows

Download it from https://sourceforge.net/projects/qcachegrindwin/

Advanced usage

Profile trigger

Profiling is enabled at request startup when one of these is true:

  • The environment variable MEMPROF_PROFILE is non-empty
  • $_GET["MEMPROF_PROFILE"] is non-empty
  • $_POST["MEMPROF_PROFILE"] is non-empty

Profile flags

The MEMPROF_PROFILE variable accepts a comma-separated list of flags.

Examples of valid MEMPROF_PROFILE values:

  • 1: non-empty: profiling is enabled
  • dump_on_limit: profiling is enabled, will dump on memory limit
  • native: profiling is enabled, will profile native allocations
  • dump_on_limit,native: profiling is enabled, will profile native allocations, will dump on memory limit

List of valid flags:

  • dump_on_limit: Will dump the profile in callgrind format in /tmp or C:\Windows\Temp. The output directory can be changed with the memprof.output_dir ini setting.
  • native: Will profile native malloc() allocations, not only PHP's (This is not thread safe, see bellow).

Profiling native allocations

Memprof doesn't track native allocations by default, but this can be enabled by setting MEMPROF_PROFILE to native.

Native allocations are the allocations made outside of PHP's own memory allocator. Typically, external libraries such as libxml2 (used in the DOM extension) make native allocations. PHP can also make native allocations for persistent resources.

Enabling native allocation tracking will profile these allocations in addition to PHP's own allocations.

Note that when native tracking is enabled, the program will crash if a native library uses threads, because the underlying hooks are not thread safe.

Functions documentation

memprof_enabled()

Returns whether memory profiling is currently enabled (see above).

memprof_enabled_flags()

Returns whether memory profiling and which profiling features are enabled (see above).

memprof_dump_callgrind(resource $stream)

Dumps the current profile in callgrind format. The result can be visualized with tools such as KCacheGrind or QCacheGrind.

<?php
memprof_dump_callgrind(fopen("output", "w"));

Here is a QcacheGrind screenshot:

QCacheGrind screenshot

memprof_dump_pprof(resource $stream)

Dumps the current profile in pprof format.

<?php
memprof_dump_pprof(fopen("profile.heap", "w"));

The file can be visualized with google-perftools's pprof tool.

Display annotated call-graph in web browser or in gv:

$ pprof --web profile.heap
$ # or:
$ pprof --gv profile.heap

pprof call-graph screenshot

Output one line per function, sorted by own memory usage:

$ pprof --text profile.heap

memprof_dump_array()

Returns an array representing the current profile.

<?php
$dump = memprof_dump_array();

The array exposes the following information:

  • Inclusive and exclusive memory leaked by functions (counting only the memory that has is still not freed when memprof_dump_array is called)
  • Inclusive and exclusive blocks count of functions (number of allocations; counting only the blocks that are still not freed when memprof_dump_array is called)
  • The data is presented in call stacks. This way, if a function is called from multiple places, it is possible to see which call path caused it to leak the most memory
Example output
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
                    (
                    )
                )
            )
        )
    )
)

memprof_version()

Returns the version of the extension as a string. The version can be compared with version_compare().

Troubleshooting

  • The extensions may conflict with xdebug, blackfire, or other extensions. If that's the case for you, please report it.

PHP versions

The current branch supports PHP 7.1 to PHP 8.

The php5 branch supports PHP 5.

How it works

See INTERNALS.md

More Repositories

1

php-rdkafka

Production-ready, stable Kafka client for PHP
C
1,968
star
2

MtHaml

Multi target HAML (HAML for PHP, Twig, <your language here>)
PHP
363
star
3

vim-php-namespace

PHP namespace support for VIM. Types "use" statements for you
Vim Script
252
star
4

php-go

php-go allows to call Go code from PHP, with minimal code boilerplate
C
174
star
5

php-inotify

Inotify bindings for PHP 5, 7, and next
C
39
star
6

MtHamlBundle

Symfony2 HAML bundle
PHP
38
star
7

imagesize.js

Get the size of an image without reading or downloading it entirely
JavaScript
30
star
8

php-sema

A library for semantic analysis of PHP code
PHP
19
star
9

alb-oembed

Simple PHP oEmbed consumer library with discovery support
PHP
16
star
10

Zwig

Twig / Zend Framework adapter
PHP
16
star
11

TwigReflectionBundle

Displays what's in Twig
PHP
15
star
12

goresize

image resizing proxy written in golang
Go
12
star
13

xtrabackup-manager

xtrabackup-manager fork. Original code at https://code.google.com/p/xtrabackup-manager/
PHP
9
star
14

TwigShellBundle

Simple Twig Shell
PHP
8
star
15

Silex-MtHaml

HAML templating for Silex
PHP
8
star
16

fselectmenu

JavaScript
7
star
17

phpketama

Pure-PHP implementation of libketama, a consistent hashing library
PHP
6
star
18

php-rdkafka-doc

PHP
6
star
19

php-inotify-ffi

Pure-PHP inotify binding (FFI-based)
PHP
5
star
20

binsort

Binsort is a tool to sort files of fixed-length binary records
Go
5
star
21

AlbOpenIDServerBundle

OpenID Provider bundle
PHP
5
star
22

php-throttle

php module for throttling file upload speed
C
4
star
23

fdinfo

progress bar for quiet cli tools
C
4
star
24

OpenISETL

Scala/JVM implementation of the ISETL language
Scala
4
star
25

run

`nohup something >/dev/null 2>&1 &`; shortened
C
3
star
26

sfbootstrap

PHP
3
star
27

mediawiki-php-FastStringSearch

Github mirror of PHP extension FastStringSearch - our actual code is hosted with Gerrit (please see https://www.mediawiki.org/wiki/Developer_access for contributing)
C
2
star
28

zf

zf mirror
PHP
1
star
29

iterm-to-neovim

Converts Iterm2 color schemes to neovim g:terminal_color_x
Go
1
star
30

jQuery.event.queueHandler

Queues handlers to be ran after the current event's handlers have been ran
JavaScript
1
star
31

graphql-demo

A Symfony application demoing a simple GraphQL API
PHP
1
star