phptop - print system ressource usage statistics from PHP scripts


phptop [options]


phptop prints per query and average metrics comparable to the 'time' program or shell builtin: wallclock, user and system CPU time along with memory and other ressources usage. It can be used from the command line to diagnose performance problem in quasi real time (minimum sampling is 1 minute) with minimal overhead, or to generate HTML reports.

Performance data is measured by a simple PHP hook (phptop_hook.php) which is automatically run on every PHP script execution via the auto_prepend PHP option. These data are collected in your web server error log, provided you have setup PHP to log errors (\fPlog_errors = On\fP) and not display them in your regular output (display_errors = Off) - which should be the case of any sane production server.

The phptop command will then parse those error logs and output useful statistics (see INTERPRETATION below).


-a, --average

Show per-hit average values instead of cumulated time.

-c, --count N

Limit output to top N URLs (default is 10).

-f, --full-query

Consider full URL with CGI parameters (ie. do not strip ?param=...).

-h, --help

Display a short options summary.

-l, --log path

Logfiles to parse, you may use several -l options and wildcards in paths. Be careful to quote your wildcards in order they are not interpreted by your shell. If no -l options are used, try a few guesses.

-o, --output mode

Output mode: text or html (default is 'text').

-p, --path-only

Only print URL paths, skip the http://<host> prefix.

-r, --relative

Show time values relative to the sample period (see -t). For instance, a cumulated 30sec user time for a 300sec sample will be shown as '10%'. Hits are also printed relative to the total of parsed records.

-s, --sort key

Sort by hit, time, user, sys or mem (default is 'hit'). You may use several -s options, they will generate as much statistics in one go (hence reusing the parsing effort efficiently).

-t, --time N

Parse data from now back to N seconds (default is 300, ie. 5 minutes).

-v, --version

Display version number and copyright information.


Using phptop to print the top CPU (user) consumers for the last 10min:

phptop -l /path/to/error.log -t 600

Getting stats from the last 10 minutes, sorted by hits, from well known log files:

phptop -p

Hint: on a given server, define a shell alias which already sets the proper error log paths. This way you don't have to repeat them again. Bash recipe:

$ echo "alias phptop='phptop -l /home/*/log/error.log'" >>.bashrc
$ source .bashrc
$ phptop -t60


Wallclock, system and user times are cumulated for similar URLs, and the total per URL is shown. It is an absolute time value which must be related to your observation window (-t option). The wallclock time is not a very interesting measure, since it depends on your server ressources, on the client and on the client-server bandwidth, minus buffering effects. Interpret it with much caution.

The user and system time are CPU ressources. For a one minute observation window (-t 60), on a quad-core system you have 4 minutes (240 seconds) worth of CPU time to be split between user (CPU running application code), system (CPU running kernel code) and idle (CPU waiting I/O or doing nothing). With --relative, the same system will show up to 400% worth of CPU time. On a busy and healthy server, user and system time add up to the whole available CPU time. If your user and system total time is low and far from the available CPU time, consult your server loadavg: if it's high (more than your number of CPUs), your server is probably waiting on I/O (more often disk than network); if it's low, your application might be waiting on remote services (think remote HTTP APIs) which are slow or not responding.

The memory figures can't be added, it would not make any sense. Instead simple satistics like peak (maximum) and average memory per URL are computed. The peak memory usage is very interesting when running phptop over a large time window (one day or more) to figure out your optimal PHP memory_limit figure, which is itself very useful for proper configuration and usage of system ressources (number of PHP processes, SQL server connections, and so on). Over a short time window it also acts as a poor man's profiler, and can spot.


phptop hooks into existing code via the auto_prepend_file PHP option. This option might be set and overriden at different levels by other programs (global, per-directory, per-vhost, etc). Since phptop has been verified to have no measurable impact on heavy production servers, it is considered to be a good idea to enable it globally. If your server uses several log files (typically one per virtual host), you will be able to only pickup needed data at analysis time (which is the potentially costly phase).

phptop records data via the error_log() PHP instruction. The author considers that any sane server setup should have a working error log, and it would have been inefficient and dangerous to handle custom logging (which would obviously end up firing lots of open/write/close, not being properly rotated and so on). This method is efficient and safe, but it has some drawbacks, see BUGS below.

At analysis time (when launching phptop itself), care has been taken to read and parse only the needed amount of data. Most importantly it will use the tac(1) command to 'reverse tail' the error logs, and default to a slower method if this command is not found. phptop can parse plain and gzipped log files.

The analysis process itself is mostly CPU bound if your error log sits on a reasonably available storage, and runs at approx. 15,000 samples/sec on a 2.4Ghz Intel core. That is why phptop output should be almost instantaneous while analysing the last minutes (eg. -t 300), even on a very busy server (100 req/sec or more).


phptop should run '-s user' as a default instead of the useless-but-look-ma-my-hits '-s hit'.

phptop pollutes error logs with non-error information, but this makes phptop fast and safe (see DISCUSSION). As a side effect, phptop won't collect data for scripts run throught the CLI SAPI (it pollutes their stderr), which is a shame.

Please file bugs on (simple registration needed), we try to solve them quickly and release often.



If set and stdout is a tty, overrides the detected terminal width. If there is no terminal (like when piping to another program), set output width.




Written by Vincent Caron

Homepage at

Copyright © 2009,2010,2011 Bearstech. License GPLv3+: GNU GPL version 3 or later <>. This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law.


time(1), getrusage(2)
Last modified 9 years ago Last modified on Aug 12, 2011, 4:16:41 PM