Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/adsr/phpspy
low-overhead sampling profiler for PHP 7+
https://github.com/adsr/phpspy
hacktoberfest performance php profiler
Last synced: 7 days ago
JSON representation
low-overhead sampling profiler for PHP 7+
- Host: GitHub
- URL: https://github.com/adsr/phpspy
- Owner: adsr
- License: mit
- Created: 2018-04-08T00:35:18.000Z (over 6 years ago)
- Default Branch: master
- Last Pushed: 2024-08-18T02:28:31.000Z (4 months ago)
- Last Synced: 2024-11-20T21:56:03.359Z (21 days ago)
- Topics: hacktoberfest, performance, php, profiler
- Language: C
- Homepage:
- Size: 356 KB
- Stars: 1,432
- Watchers: 56
- Forks: 66
- Open Issues: 16
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-php - PHPSpy - A low-overhead sampling profiler. (Table of Contents / Debugging and Profiling)
- awesome-php-extensions - php-spy - 性能分析工具 (代码分析)
- awesome-php-cn - PHPSpy - 一个低开销抽样分析器. (目录 / 调试和性能分析 Debugging and Profiling)
- awesome-projects - PHPSpy - A low-overhead sampling profiler. (PHP / Debugging and Profiling)
- php-awesome - phpspy - PHP 性能分析工具,支持火焰图 (类库 / 代码检查/静态分析)
- awesome-php - PHPSpy - A low-overhead sampling profiler. (Table of Contents / Debugging and Profiling)
README
# phpspy
phpspy is a low-overhead sampling profiler for PHP. It works with non-ZTS PHP
7.0+ with CLI, Apache, and FPM SAPIs on 64-bit Linux 3.2+.[![Build Status](https://github.com/adsr/phpspy/actions/workflows/phpspy_test.yml/badge.svg)](https://github.com/adsr/phpspy/actions/workflows/phpspy_test.yml)
### Demos
You can profile PHP scripts:
![child](https://i.imgur.com/QE8iJLA.gif)
You can attach to running PHP processes:
![attach cli](https://i.imgur.com/HubBqo0.gif)
![attach httpd](https://i.imgur.com/KVY3KXq.gif)
It has a top-like mode:
![top](https://i.imgur.com/Y0NJJ1C.gif)
It can collect request info, memory usage, and variables:
![advanced](https://i.imgur.com/nlUfCWT.gif)
You can also use it to make flamegraphs like this:
![FlameGraph example](https://i.imgur.com/e6P9Arp.png)
All with no changes to your application and minimal overhead.
### Synopsis
$ git clone https://github.com/adsr/phpspy.git
Cloning into 'phpspy'...
...
$ cd phpspy
$ make
...
$ sudo ./phpspy --limit=1000 --pid=$(pgrep -n httpd) >traces
...
$ ./stackcollapse-phpspy.pl flame.svg
$ google-chrome flame.svg # View flame.svg in browser### Build options
$ make # Use built-in structs
$ # or
$ USE_ZEND=1 make ... # Use Zend structs (requires PHP development headers)### Usage
$ ./phpspy -h
Usage:
phpspy [options] -p
phpspy [options] -P
phpspy [options] [--]Options:
-h, --help Show this help
-p, --pid= Trace PHP process at `pid`
-P, --pgrep= Concurrently trace processes that
match pgrep `args` (see also `-T`)
-T, --threads= Set number of threads to use with `-P`
(default: 16)
-s, --sleep-ns= Sleep `ns` nanoseconds between traces
(see also `-H`) (default: 10101010)
-H, --rate-hz= Trace `hz` times per second
(see also `-s`) (default: 99)
-V, --php-version= Set PHP version
(default: auto;
supported: 70 71 72 73 74 80 81 82)
-l, --limit= Limit total number of traces to capture
(approximate limit in pgrep mode)
(default: 0; 0=unlimited)
-i, --time-limit-ms= Stop tracing after `ms` milliseconds
(second granularity in pgrep mode)
(default: 0; 0=unlimited)
-n, --max-depth= Set max stack trace depth
(default: -1; -1=unlimited)
-r, --request-info= Set request info parts to capture
(q=query c=cookie u=uri p=path
capital=negation)
(default: QCUP; none)
-m, --memory-usage Capture peak and current memory usage
with each trace (requires target PHP
process to have debug symbols)
-o, --output= Write phpspy output to `path`
(default: -; -=stdout)
-O, --child-stdout= Write child stdout to `path`
(default: phpspy.%d.out)
-E, --child-stderr= Write child stderr to `path`
(default: phpspy.%d.err)
-x, --addr-executor-globals= Set address of executor_globals in hex
(default: 0; 0=find dynamically)
-a, --addr-sapi-globals= Set address of sapi_globals in hex
(default: 0; 0=find dynamically)
-1, --single-line Output in single-line mode
-b, --buffer-size= Set output buffer size to `size`.
Note: In `-P` mode, setting this
above PIPE_BUF (4096) may lead to
interlaced writes across threads
unless `-J m` is specified.
(default: 4096)
-f, --filter= Filter output by POSIX regex
(default: none)
-F, --filter-negate= Same as `-f` except negated
-d, --verbose-fields= Set verbose output fields
(p=pid t=timestamp
capital=negation)
(default: PT; none)
-c, --continue-on-error Attempt to continue tracing after
encountering an error
-#, --comment= Ignored; intended for self-documenting
commands
-@, --nothing Ignored
-v, --version Print phpspy version and exitExperimental options:
-j, --event-handler= Set event handler (fout, callgrind)
(default: fout)
-J, --event-handler-opts= Set event handler options
(fout: m=use mutex to prevent
interlaced writes on stdout in `-P`
mode)
-S, --pause-process Pause process while reading stacktrace
(unsafe for production!)
-e, --peek-var= Peek at the contents of the var located
at `varspec`, which has the format:
@:
@:-
e.g., xyz@/path/to.php:10-20
-g, --peek-global= Peek at the contents of a global var
located at `glospec`, which has
the format: .
where is one of:
post|get|cookie|server|files|globals
e.g., server.REQUEST_TIME
-t, --top Show dynamic top-like output### Example (variable peek)
$ sudo ./phpspy -e 'i@/var/www/test/lib/test.php:12' -p $(pgrep -n httpd) | grep varpeek
# varpeek i@/var/www/test/lib/test.php:12 = 42
# varpeek i@/var/www/test/lib/test.php:12 = 42
# varpeek i@/var/www/test/lib/test.php:12 = 43
# varpeek i@/var/www/test/lib/test.php:12 = 44
...### Example (pgrep daemon mode)
$ sudo ./phpspy -H1 -T4 -P '-x php'
0 proc_open :-1
1 system_with_timeout /home/adam/php-src/run-tests.php:1137
2 run_test /home/adam/php-src/run-tests.php:1937
3 run_all_tests /home/adam/php-src/run-tests.php:1215
4 /home/adam/php-src/run-tests.php:986
# - - - - -
...
^C
main_pgrep finished gracefully### Example (httpd)
$ sudo ./phpspy -p $(pgrep -n httpd)
0 Memcached::get :-1
1 Cache_MemcachedToggleable::get /foo/bar/lib/Cache/MemcachedToggleable.php:26
2 Cache_Memcached::get /foo/bar/lib/Cache/Memcached.php:251
3 IpDb_CacheBase::getFromCache /foo/bar/lib/IpDb/CacheBase.php:165
4 IpDb_CacheBase::get /foo/bar/lib/IpDb/CacheBase.php:107
5 IpDb_CacheBase::contains /foo/bar/lib/IpDb/CacheBase.php:70
6 IpDb_Botnet::has /foo/bar/lib/IpDb/Botnet.php:32
7 Security_Rule_IpAddr::__construct /foo/bar/lib/Security/Rule/IpAddr.php:53
8 Security_Rule_HttpRequestContext::initVariables /foo/bar/lib/Security/Rule/HttpRequestContext.php:22
9 Security_Rule_Context::__construct /foo/bar/lib/Security/Rule/Context.php:44
10 Security_Rule_Engine::getContextByName /foo/bar/lib/Security/Rule/Engine.php:225
11 Security_Rule_Engine::getContextByLocation /foo/bar/lib/Security/Rule/Engine.php:210
12 Security_Rule_Engine::evaluateActionRules /foo/bar/lib/Security/Rule/Engine.php:116
13 /foo/bar/lib/bootstrap/api.php:49
14 /foo/bar/htdocs/v3/public.php:5
# - - - - -
...### Example (cli child)
$ ./phpspy -- php -r 'usleep(100000);'
0 usleep :-1
1 :-10 usleep :-1
1 :-10 usleep :-1
1 :-10 usleep :-1
1 :-10 usleep :-1
1 :-10 usleep :-1
1 :-1process_vm_readv: No such process
### Example (cli attach)
$ php -r 'sleep(10);' &
[1] 28586
$ sudo ./phpspy -p 28586
0 sleep :-1
1 :-1
...### Example (docker)
$ docker build . -t phpspy
$ docker run -it --cap-add SYS_PTRACE phpspy:latest ./phpspy/phpspy -V73 -r -- php -r 'sleep(1);'
0 sleep :-1
1 :-1
...### Known bugs
* phpspy may not work with a chrooted mod_php process whose binary lives inside overlayfs. (See [#109][8].)
### See also
* [rbspy][0] for Ruby, the original inspiration for phpspy
* [py-spy][1] for Python
* [Xdebug profiler][2], instrumented profiler
* [php-profiler][3], similar to phpspy but pure PHP
* [sample_prof][4]
* [php-trace][5]
* [Blackfire][6], commercial
* [Tideways][7], commercial### TODO
* See `grep -ri todo`
* See https://github.com/adsr/phpspy/issues[0]: https://github.com/rbspy/rbspy
[1]: https://github.com/benfred/py-spy
[2]: http://www.xdebug.org/docs/profiler
[3]: https://github.com/sj-i/php-profiler
[4]: https://github.com/nikic/sample_prof
[5]: https://github.com/krakjoe/trace
[6]: https://blackfire.io/
[7]: https://tideways.io/
[8]: https://github.com/adsr/phpspy/issues/109