{"id":13560706,"url":"https://github.com/adsr/phpspy","last_synced_at":"2025-05-14T15:00:26.438Z","repository":{"id":40524459,"uuid":"128580589","full_name":"adsr/phpspy","owner":"adsr","description":"low-overhead sampling profiler for PHP 7+","archived":false,"fork":false,"pushed_at":"2025-03-12T18:50:41.000Z","size":357,"stargazers_count":1446,"open_issues_count":16,"forks_count":67,"subscribers_count":54,"default_branch":"master","last_synced_at":"2025-04-11T15:56:51.759Z","etag":null,"topics":["hacktoberfest","performance","php","profiler"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/adsr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-08T00:35:18.000Z","updated_at":"2025-04-11T03:16:59.000Z","dependencies_parsed_at":"2025-03-28T05:00:25.414Z","dependency_job_id":"17f4ab7d-a83e-4747-9a37-829012720a2a","html_url":"https://github.com/adsr/phpspy","commit_stats":{"total_commits":232,"total_committers":19,"mean_commits":"12.210526315789474","dds":"0.18965517241379315","last_synced_commit":"5256d67f53aa65cbdff87ab9d848f220e36a4e79"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adsr%2Fphpspy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adsr%2Fphpspy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adsr%2Fphpspy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adsr%2Fphpspy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adsr","download_url":"https://codeload.github.com/adsr/phpspy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254168099,"owners_count":22026084,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["hacktoberfest","performance","php","profiler"],"created_at":"2024-08-01T13:00:48.880Z","updated_at":"2025-05-14T15:00:25.879Z","avatar_url":"https://github.com/adsr.png","language":"C","readme":"# phpspy\n\nphpspy is a low-overhead sampling profiler for PHP. It works with non-ZTS PHP\n7.0+ with CLI, Apache, and FPM SAPIs on 64-bit Linux 3.2+.\n\n[![Build Status](https://github.com/adsr/phpspy/actions/workflows/phpspy_test.yml/badge.svg)](https://github.com/adsr/phpspy/actions/workflows/phpspy_test.yml)\n\n### Demos\n\nYou can profile PHP scripts:\n\n![child](https://i.imgur.com/QE8iJLA.gif)\n\nYou can attach to running PHP processes:\n\n![attach cli](https://i.imgur.com/HubBqo0.gif)\n\n![attach httpd](https://i.imgur.com/KVY3KXq.gif)\n\nIt has a top-like mode:\n\n![top](https://i.imgur.com/Y0NJJ1C.gif)\n\nIt can collect request info, memory usage, and variables:\n\n![advanced](https://i.imgur.com/nlUfCWT.gif)\n\nYou can also use it to make flamegraphs like this:\n\n![FlameGraph example](https://i.imgur.com/e6P9Arp.png)\n\nAll with no changes to your application and minimal overhead.\n\n### Synopsis\n\n    $ git clone https://github.com/adsr/phpspy.git\n    Cloning into 'phpspy'...\n    ...\n    $ cd phpspy\n    $ make\n    ...\n    $ sudo ./phpspy --limit=1000 --pid=$(pgrep -n httpd) \u003etraces\n    ...\n    $ ./stackcollapse-phpspy.pl \u003ctraces | ./vendor/flamegraph.pl \u003eflame.svg\n    $ google-chrome flame.svg # View flame.svg in browser\n\n### Build options\n\n    $ make                   # Use built-in structs\n    $ # or\n    $ USE_ZEND=1 make ...    # Use Zend structs (requires PHP development headers)\n\n### Usage\n    $ ./phpspy -h\n    Usage:\n      phpspy [options] -p \u003cpid\u003e\n      phpspy [options] -P \u003cpgrep-args\u003e\n      phpspy [options] [--] \u003ccmd\u003e\n\n    Options:\n      -h, --help                         Show this help\n      -p, --pid=\u003cpid\u003e                    Trace PHP process at `pid`\n      -P, --pgrep=\u003cargs\u003e                 Concurrently trace processes that\n                                           match pgrep `args` (see also `-T`)\n      -T, --threads=\u003cnum\u003e                Set number of threads to use with `-P`\n                                           (default: 16)\n      -s, --sleep-ns=\u003cns\u003e                Sleep `ns` nanoseconds between traces\n                                           (see also `-H`) (default: 10101010)\n      -H, --rate-hz=\u003chz\u003e                 Trace `hz` times per second\n                                           (see also `-s`) (default: 99)\n      -V, --php-version=\u003cver\u003e            Set PHP version\n                                           (default: auto;\n                                           supported: 70 71 72 73 74 80 81 82)\n      -l, --limit=\u003cnum\u003e                  Limit total number of traces to capture\n                                           (approximate limit in pgrep mode)\n                                           (default: 0; 0=unlimited)\n      -i, --time-limit-ms=\u003cms\u003e           Stop tracing after `ms` milliseconds\n                                           (second granularity in pgrep mode)\n                                           (default: 0; 0=unlimited)\n      -n, --max-depth=\u003cmax\u003e              Set max stack trace depth\n                                           (default: -1; -1=unlimited)\n      -r, --request-info=\u003copts\u003e          Set request info parts to capture\n                                           (q=query c=cookie u=uri p=path\n                                           capital=negation)\n                                           (default: QCUP; none)\n      -m, --memory-usage                 Capture peak and current memory usage\n                                           with each trace (requires target PHP\n                                           process to have debug symbols)\n      -o, --output=\u003cpath\u003e                Write phpspy output to `path`\n                                           (default: -; -=stdout)\n      -O, --child-stdout=\u003cpath\u003e          Write child stdout to `path`\n                                           (default: phpspy.%d.out)\n      -E, --child-stderr=\u003cpath\u003e          Write child stderr to `path`\n                                           (default: phpspy.%d.err)\n      -x, --addr-executor-globals=\u003chex\u003e  Set address of executor_globals in hex\n                                           (default: 0; 0=find dynamically)\n      -a, --addr-sapi-globals=\u003chex\u003e      Set address of sapi_globals in hex\n                                           (default: 0; 0=find dynamically)\n      -1, --single-line                  Output in single-line mode\n      -b, --buffer-size=\u003csize\u003e           Set output buffer size to `size`.\n                                           Note: In `-P` mode, setting this\n                                           above PIPE_BUF (4096) may lead to\n                                           interlaced writes across threads\n                                           unless `-J m` is specified.\n                                           (default: 4096)\n      -f, --filter=\u003cregex\u003e               Filter output by POSIX regex\n                                           (default: none)\n      -F, --filter-negate=\u003cregex\u003e        Same as `-f` except negated\n      -d, --verbose-fields=\u003copts\u003e        Set verbose output fields\n                                           (p=pid t=timestamp\n                                           capital=negation)\n                                           (default: PT; none)\n      -c, --continue-on-error            Attempt to continue tracing after\n                                           encountering an error\n      -#, --comment=\u003cany\u003e                Ignored; intended for self-documenting\n                                           commands\n      -@, --nothing                      Ignored\n      -v, --version                      Print phpspy version and exit\n\n    Experimental options:\n      -j, --event-handler=\u003chandler\u003e      Set event handler (fout, callgrind)\n                                           (default: fout)\n      -J, --event-handler-opts=\u003copts\u003e    Set event handler options\n                                           (fout: m=use mutex to prevent\n                                           interlaced writes on stdout in `-P`\n                                           mode)\n      -S, --pause-process                Pause process while reading stacktrace\n                                           (unsafe for production!)\n      -e, --peek-var=\u003cvarspec\u003e           Peek at the contents of the var located\n                                           at `varspec`, which has the format:\n                                           \u003cvarname\u003e@\u003cpath\u003e:\u003clineno\u003e\n                                           \u003cvarname\u003e@\u003cpath\u003e:\u003cstart\u003e-\u003cend\u003e\n                                           e.g., xyz@/path/to.php:10-20\n      -g, --peek-global=\u003cglospec\u003e        Peek at the contents of a global var\n                                           located at `glospec`, which has\n                                           the format: \u003cglobal\u003e.\u003ckey\u003e\n                                           where \u003cglobal\u003e is one of:\n                                           post|get|cookie|server|files|globals\n                                           e.g., server.REQUEST_TIME\n      -t, --top                          Show dynamic top-like output\n\n### Example (variable peek)\n\n    $ sudo ./phpspy -e 'i@/var/www/test/lib/test.php:12' -p $(pgrep -n httpd) | grep varpeek\n    # varpeek i@/var/www/test/lib/test.php:12 = 42\n    # varpeek i@/var/www/test/lib/test.php:12 = 42\n    # varpeek i@/var/www/test/lib/test.php:12 = 43\n    # varpeek i@/var/www/test/lib/test.php:12 = 44\n    ...\n\n### Example (pgrep daemon mode)\n\n    $ sudo ./phpspy -H1 -T4 -P '-x php'\n    0 proc_open \u003cinternal\u003e:-1\n    1 system_with_timeout /home/adam/php-src/run-tests.php:1137\n    2 run_test /home/adam/php-src/run-tests.php:1937\n    3 run_all_tests /home/adam/php-src/run-tests.php:1215\n    4 \u003cmain\u003e /home/adam/php-src/run-tests.php:986\n    # - - - - -\n    ...\n    ^C\n    main_pgrep finished gracefully\n\n### Example (httpd)\n\n    $ sudo ./phpspy -p $(pgrep -n httpd)\n    0 Memcached::get \u003cinternal\u003e:-1\n    1 Cache_MemcachedToggleable::get /foo/bar/lib/Cache/MemcachedToggleable.php:26\n    2 Cache_Memcached::get /foo/bar/lib/Cache/Memcached.php:251\n    3 IpDb_CacheBase::getFromCache /foo/bar/lib/IpDb/CacheBase.php:165\n    4 IpDb_CacheBase::get /foo/bar/lib/IpDb/CacheBase.php:107\n    5 IpDb_CacheBase::contains /foo/bar/lib/IpDb/CacheBase.php:70\n    6 IpDb_Botnet::has /foo/bar/lib/IpDb/Botnet.php:32\n    7 Security_Rule_IpAddr::__construct /foo/bar/lib/Security/Rule/IpAddr.php:53\n    8 Security_Rule_HttpRequestContext::initVariables /foo/bar/lib/Security/Rule/HttpRequestContext.php:22\n    9 Security_Rule_Context::__construct /foo/bar/lib/Security/Rule/Context.php:44\n    10 Security_Rule_Engine::getContextByName /foo/bar/lib/Security/Rule/Engine.php:225\n    11 Security_Rule_Engine::getContextByLocation /foo/bar/lib/Security/Rule/Engine.php:210\n    12 Security_Rule_Engine::evaluateActionRules /foo/bar/lib/Security/Rule/Engine.php:116\n    13 \u003cmain\u003e /foo/bar/lib/bootstrap/api.php:49\n    14 \u003cmain\u003e /foo/bar/htdocs/v3/public.php:5\n    # - - - - -\n    ...\n\n### Example (cli child)\n\n    $ ./phpspy -- php -r 'usleep(100000);'\n    0 usleep \u003cinternal\u003e:-1\n    1 \u003cmain\u003e \u003cinternal\u003e:-1\n\n    0 usleep \u003cinternal\u003e:-1\n    1 \u003cmain\u003e \u003cinternal\u003e:-1\n\n    0 usleep \u003cinternal\u003e:-1\n    1 \u003cmain\u003e \u003cinternal\u003e:-1\n\n    0 usleep \u003cinternal\u003e:-1\n    1 \u003cmain\u003e \u003cinternal\u003e:-1\n\n    0 usleep \u003cinternal\u003e:-1\n    1 \u003cmain\u003e \u003cinternal\u003e:-1\n\n    0 usleep \u003cinternal\u003e:-1\n    1 \u003cmain\u003e \u003cinternal\u003e:-1\n\n    process_vm_readv: No such process\n\n### Example (cli attach)\n\n    $ php -r 'sleep(10);' \u0026\n    [1] 28586\n    $ sudo ./phpspy -p 28586\n    0 sleep \u003cinternal\u003e:-1\n    1 \u003cmain\u003e \u003cinternal\u003e:-1\n    ...\n\n### Example (docker)\n    $ docker build . -t phpspy\n    $ docker run -it --cap-add SYS_PTRACE phpspy:latest ./phpspy/phpspy -V73 -r -- php -r 'sleep(1);'\n    0 sleep \u003cinternal\u003e:-1\n    1 \u003cmain\u003e \u003cinternal\u003e:-1\n    ...\n\n### Known bugs\n\n* phpspy may not work with a chrooted mod_php process whose binary lives inside overlayfs. (See [#109][8].)\n\n### See also\n\n* [rbspy][0] for Ruby, the original inspiration for phpspy\n* [py-spy][1] for Python\n* [Xdebug profiler][2], instrumented profiler\n* [php-profiler][3], similar to phpspy but pure PHP\n* [sample_prof][4]\n* [php-trace][5]\n* [Blackfire][6], commercial\n* [Tideways][7], commercial\n\n### TODO\n\n* See `grep -ri todo`\n* See https://github.com/adsr/phpspy/issues\n\n[0]: https://github.com/rbspy/rbspy\n[1]: https://github.com/benfred/py-spy\n[2]: http://www.xdebug.org/docs/profiler\n[3]: https://github.com/sj-i/php-profiler\n[4]: https://github.com/nikic/sample_prof\n[5]: https://github.com/krakjoe/trace\n[6]: https://blackfire.io/\n[7]: https://tideways.io/\n[8]: https://github.com/adsr/phpspy/issues/109\n","funding_links":[],"categories":["C","目录","Table of Contents","PHP","代码分析","P8 Améliorez une application existante de ToDo \u0026 Co","Others","类库"],"sub_categories":["调试和性能分析 Debugging and Profiling","Debugging and Profiling","Performance de code","代码检查/静态分析"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadsr%2Fphpspy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadsr%2Fphpspy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadsr%2Fphpspy/lists"}