reliforp / reli-prof
PHP的一个采样分析器或内存分析器,使用PHP编写,可以从进程外部读取运行中的PHP虚拟机信息。
Requires
- php: ^8.1
- ext-ffi: *
- ext-filter: *
- ext-json: *
- ext-pcntl: *
- amphp/amp: 3.0.0
- amphp/parallel: 2.2.4
- hassankhan/config: 3.1.0
- monolog/monolog: 3.5.0
- php-di/php-di: 7.0.6
- sj-i/php-cast: 1.0.0
- symfony/console: 6.3.8
- webmozart/assert: 1.11.0
Requires (Dev)
- ext-posix: *
- jetbrains/phpstorm-stubs: 2023.3
- mockery/mockery: 1.6.7
- php-coveralls/php-coveralls: 2.7.0
- phpunit/phpunit: 10.5.3
- psalm/phar: ^5.11
- squizlabs/php_codesniffer: 3.8.0
- 0.12.x-dev
- 0.11.x-dev
- 0.11.4
- 0.11.3
- 0.11.2
- 0.11.1
- 0.11.0
- 0.10.x-dev
- 0.10.3
- 0.10.2
- 0.10.1
- 0.10.0
- 0.9.x-dev
- 0.9.4
- 0.9.3
- 0.9.2
- 0.9.1
- 0.9.0
- 0.8.x-dev
- 0.8.0
- 0.7.x-dev
- 0.7.0
- 0.6.x-dev
- 0.6.1
- 0.6.0
- 0.5.x-dev
- 0.5.0
- 0.4.2
- 0.4.1
- 0.4.0
- 0.3.8
- 0.3.7
- 0.3.6
- 0.3.5
- 0.3.4
- 0.3.3
- 0.3.2
- 0.3.1
- 0.3.0
- 0.2.1
- 0.2.0
- 0.1.0
- 0.0.9
- 0.0.8
- 0.0.7
- 0.0.6
- 0.0.5
- 0.0.4
- 0.0.3
- 0.0.2
- 0.0.1
- dev-renovate/major-symfony
- dev-renovate/symfony
- dev-renovate/phpunit-phpunit-11.x
- dev-renovate/phpunit-phpunit-10.x
- dev-renovate/squizlabs-php_codesniffer-3.x
- dev-renovate/psalm-phar-5.x-lockfile
- dev-renovate/jetbrains-phpstorm-stubs-2024.x
- dev-renovate/php-di-php-di-7.x
- dev-renovate/monolog-monolog-3.x
- dev-unloaded-ro-mapping
- dev-fix-zts-detection
- dev-support-stripped-zts
- dev-renovate/php-8.x
- dev-update-issue-template
- dev-backport-fix-doc
- dev-dwarf
- dev-tracing-in-c
- dev-phpcon2020
- dev-experiment-opcode-tracer
This package is auto-updated.
Last update: 2024-09-21 06:32:56 UTC
README
Reli是一个使用PHP编写的采样分析器(或虚拟机状态检查器)。它可以读取进程外部运行的PHP脚本信息。它是一个独立的命令行工具,因此目标程序不需要任何修改。此工具的前名为sj-i/php-profiler。
我能用这个做什么?
- 检测和可视化PHP脚本中的瓶颈
- 它不仅提供函数级别的分析,还提供行级别或指令级别解析
- 即使大量快速函数被调用,也不会产生累积开销,因为它是一个采样分析器(参见以下链接,tideways,xhprof,以及xdebug的分析器,许多分析器都有这种开销)
- 调查错误或性能失败的原因
- 即使PHP脚本处于无法解释的无响应状态,您也可以使用它来了解其内部正在做什么。
- 查找内存瓶颈或内存泄漏
它的工作原理
它通过以下技术实现
- 解析解释器的ELF二进制文件
- 从/proc/
/maps读取内存映射 - 通过ptrace(2)和process_vm_readv(2)通过FFI读取外部进程的内存
- 分析PHP虚拟机(即Zend引擎)中的内部数据结构
如果您有一些额外的CPU资源,此软件的开销将是可以忽略不计的。
与phpspy的区别,何时使用reli
Reli深受adsr/phpspy的启发。
这两个之间的主要区别在于reli几乎完全使用PHP编写,而phpspy则使用C编写。在分析时,有时您想自定义获取什么信息和如何获取。如果PHP开发者的可定制性很重要,您可以使用此软件以性能为代价。尽管如此,我们希望代价不是太大。
此外,reli可以从ZTS解释器中找到VM状态。例如,在守护进程模式下,通过ext-parallel启动的线程的跟踪会自动检索。目前这只能使用phpspy完成。Reli还提供仅从目标获取EG地址的功能,因此如果您希望使用phpspy进行实际分析,即使目标为ZTS也可以。
reli的其他功能,phpspy目前还没有包括
- 输出更准确的行号
- 使用PHP模板自定义输出格式
- 获取PHP-VM的运行指令
- 自动从精简的PHP二进制文件中检索目标PHP版本
- 以speedscope格式输出跟踪
- 深入分析目标进程的内存使用情况
没有特别的原因说明为什么这些功能不能在phpspy端实现,因此将来可能在phpspy上实现。
另一方面,phpspy可以做一些reli目前还不能做的事情。
- 重定向子进程的输出
- 强制EG的地址
- 以更快的速度运行,开销更低。
- 等等。
将来可以用reli完成的大部分内容,都可以用phpspy完成。
要求
支持的PHP版本
执行
- PHP 8.1+ (NTS / ZTS)
- 64位Linux x86_64
- 必须启用FFI扩展。
- 必须启用PCNTL扩展。
目标
- PHP 7.0+ (NTS / ZTS)
- 64位Linux x86_64
在针对ZTS时,目标进程必须加载libpthread.so库,并且您必须拥有解释器和libpthread.so的未剥离的二进制文件,以便从TLS中找到EG。
安装
从Composer安装
composer create-project reliforp/reli-prof
cd reli-prof
./reli
从Git安装
git clone git@github.com:reliforp/reli-prof.git
cd reli-prof
composer install
./reli
从Docker安装
docker pull reliforp/reli-prof
docker run -it --security-opt="apparmor=unconfined" --cap-add=SYS_PTRACE --pid=host reliforp/reli-prof
使用方法
获取调用跟踪
./reli inspector:trace --help Description: periodically get call trace from an outer process or thread Usage: inspector:trace [options] [--] [<cmd> [<args>...]] Arguments: cmd command to execute as a target: either pid (via -p/--pid) or cmd must be specified args command line arguments for cmd Options: -p, --pid=PID process id -d, --depth[=DEPTH] max depth -s, --sleep-ns[=SLEEP-NS] nanoseconds between traces (default: 1000 * 1000 * 10) -r, --max-retries[=MAX-RETRIES] max retries on contiguous errors of read (default: 10) -S, --stop-process[=STOP-PROCESS] stop the target process while reading its trace (default: off) --php-regex[=PHP-REGEX] regex to find the php binary loaded in the target process --libpthread-regex[=LIBPTHREAD-REGEX] regex to find the libpthread.so loaded in the target process --php-version[=PHP-VERSION] php version (auto|v7[0-4]|v8[0123]) of the target (default: auto) --php-path[=PHP-PATH] path to the php binary (only needed in tracing chrooted ZTS target) --libpthread-path[=LIBPTHREAD-PATH] path to the libpthread.so (only needed in tracing chrooted ZTS target) -t, --template[=TEMPLATE] template name (phpspy|phpspy_with_opcode|json_lines) (default: phpspy) -o, --output=OUTPUT path to write output from this tool (default: stdout) -h, --help Display help for the given command. When no command is given display help for the list command -q, --quiet Do not output any message -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
守护进程模式
./reli inspector:daemon --help Description: concurrently get call traces from processes whose command-lines match a given regex Usage: inspector:daemon [options] Options: -P, --target-regex=TARGET-REGEX regex to find target processes which have matching command-line (required) -T, --threads[=THREADS] number of workers (default: 8) -d, --depth[=DEPTH] max depth -s, --sleep-ns[=SLEEP-NS] nanoseconds between traces (default: 1000 * 1000 * 10) -r, --max-retries[=MAX-RETRIES] max retries on contiguous errors of read (default: 10) -S, --stop-process[=STOP-PROCESS] stop the target process while reading its trace (default: off) --php-regex[=PHP-REGEX] regex to find the php binary loaded in the target process --libpthread-regex[=LIBPTHREAD-REGEX] regex to find the libpthread.so loaded in the target process --php-version[=PHP-VERSION] php version (auto|v7[0-4]|v8[0123]) of the target (default: auto) --php-path[=PHP-PATH] path to the php binary (only needed in tracing chrooted ZTS target) --libpthread-path[=LIBPTHREAD-PATH] path to the libpthread.so (only needed in tracing chrooted ZTS target) -t, --template[=TEMPLATE] template name (phpspy|phpspy_with_opcode|json_lines) (default: phpspy) -o, --output=OUTPUT path to write output from this tool (default: stdout) -h, --help Display help for the given command. When no command is given display help for the list command -q, --quiet Do not output any message -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
类似top的模式
./reli inspector:top --help Description: show an aggregated view of traces in real time in a form similar to the UNIX top command. Usage: inspector:top [options] Options: -P, --target-regex=TARGET-REGEX regex to find target processes which have matching command-line (required) -T, --threads[=THREADS] number of workers (default: 8) -d, --depth[=DEPTH] max depth -s, --sleep-ns[=SLEEP-NS] nanoseconds between traces (default: 1000 * 1000 * 10) -r, --max-retries[=MAX-RETRIES] max retries on contiguous errors of read (default: 10) -S, --stop-process[=STOP-PROCESS] stop the target process while reading its trace (default: off) --php-regex[=PHP-REGEX] regex to find the php binary loaded in the target process --libpthread-regex[=LIBPTHREAD-REGEX] regex to find the libpthread.so loaded in the target process --php-version[=PHP-VERSION] php version (auto|v7[0-4]|v8[0123]) of the target (default: auto) --php-path[=PHP-PATH] path to the php binary (only needed in tracing chrooted ZTS target) --libpthread-path[=LIBPTHREAD-PATH] path to the libpthread.so (only needed in tracing chrooted ZTS target) -h, --help Display help for the given command. When no command is given display help for the list command -q, --quiet Do not output any message -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
获取EG的地址
./reli inspector:eg --help Description: get EG address from an outer process or thread Usage: inspector:eg_address [options] [--] [<cmd> [<args>...]] Arguments: cmd command to execute as a target: either pid (via -p/--pid) or cmd must be specified args command line arguments for cmd Options: -p, --pid=PID process id --php-regex[=PHP-REGEX] regex to find the php binary loaded in the target process --libpthread-regex[=LIBPTHREAD-REGEX] regex to find the libpthread.so loaded in the target process --php-version[=PHP-VERSION] php version (auto|v7[0-4]|v8[0123]) of the target (default: auto) --php-path[=PHP-PATH] path to the php binary (only needed in tracing chrooted ZTS target) --libpthread-path[=LIBPTHREAD-PATH] path to the libpthread.so (only needed in tracing chrooted ZTS target) -h, --help Display help for the given command. When no command is given display help for the list command -q, --quiet Do not output any message -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
[实验性]转储目标进程的内存使用情况
./reli inspector:memory --help Description: [experimental] get memory usage from an outer process Usage: inspector:memory [options] [--] [<cmd> [<args>...]] Arguments: cmd command to execute as a target: either pid (via -p/--pid) or cmd must be specified args command line arguments for cmd Options: --stop-process|--no-stop-process stop the process while inspecting (default: on) --pretty-print|--no-pretty-print pretty print the result (default: off) --memory-limit-error-file=MEMORY-LIMIT-ERROR-FILE file path where memory_limit is exceeded --memory-limit-error-line=MEMORY-LIMIT-ERROR-LINE line number where memory_limit is exceeded --memory-limit-error-max-depth[=MEMORY-LIMIT-ERROR-MAX-DEPTH] max attempts to trace back the VM stack on memory_limit error [default: 512] -p, --pid=PID process id --php-regex[=PHP-REGEX] regex to find the php binary loaded in the target process --libpthread-regex[=LIBPTHREAD-REGEX] regex to find the libpthread.so loaded in the target process --php-version[=PHP-VERSION] php version (auto|v7[0-4]|v8[0123]) of the target (default: auto) --php-path[=PHP-PATH] path to the php binary (only needed in tracing chrooted ZTS target) --libpthread-path[=LIBPTHREAD-PATH] path to the libpthread.so (only needed in tracing chrooted ZTS target) -h, --help Display help for the given command. When no command is given display help for the list command -q, --quiet Do not output any message -V, --version Display this application version --ansi|--no-ansi Force (or disable --no-ansi) ANSI output -n, --no-interaction Do not ask any interactive question -v|vv|vvv, --verbose Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug
示例
跟踪脚本
$ ./reli i:trace -- php -r "fgets(STDIN);" 0 fgets <internal>:-1 1 <main> <internal>:-1 0 fgets <internal>:-1 1 <main> <internal>:-1 0 fgets <internal>:-1 1 <main> <internal>:-1 <press q to exit> ...
附加到正在运行的进程
$ sudo php ./reli i:trace -p 2182685 0 time_nanosleep <internal>:-1 1 Reli\Lib\Loop\LoopMiddleware\NanoSleepMiddleware::invoke /home/sji/work/reli/src/Lib/Loop/LoopMiddleware/NanoSleepMiddleware.php:33 2 Reli\Lib\Loop\LoopMiddleware\KeyboardCancelMiddleware::invoke /home/sji/work/reli/src/Lib/Loop/LoopMiddleware/KeyboardCancelMiddleware.php:39 3 Reli\Lib\Loop\LoopMiddleware\RetryOnExceptionMiddleware::invoke /home/sji/work/reli/src/Lib/Loop/LoopMiddleware/RetryOnExceptionMiddleware.php:37 4 Reli\Lib\Loop\Loop::invoke /home/sji/work/reli/src/Lib/Loop/Loop.php:26 5 Reli\Command\Inspector\GetTraceCommand::execute /home/sji/work/reli/src/Command/Inspector/GetTraceCommand.php:133 6 Symfony\Component\Console\Command\Command::run /home/sji/work/reli/vendor/symfony/console/Command/Command.php:291 7 Symfony\Component\Console\Application::doRunCommand /home/sji/work/reli/vendor/symfony/console/Application.php:979 8 Symfony\Component\Console\Application::doRun /home/sji/work/reli/vendor/symfony/console/Application.php:299 9 Symfony\Component\Console\Application::run /home/sji/work/reli/vendor/symfony/console/Application.php:171 10 <main> /home/sji/work/reli/reli:45 0 time_nanosleep <internal>:-1 1 Reli\Lib\Loop\LoopMiddleware\NanoSleepMiddleware::invoke /home/sji/work/reli/src/Lib/Loop/LoopMiddleware/NanoSleepMiddleware.php:33 2 Reli\Lib\Loop\LoopMiddleware\KeyboardCancelMiddleware::invoke /home/sji/work/reli/src/Lib/Loop/LoopMiddleware/KeyboardCancelMiddleware.php:39 3 Reli\Lib\Loop\LoopMiddleware\RetryOnExceptionMiddleware::invoke /home/sji/work/reli/src/Lib/Loop/LoopMiddleware/RetryOnExceptionMiddleware.php:37 4 Reli\Lib\Loop\Loop::invoke /home/sji/work/reli/src/Lib/Loop/Loop.php:26 5 Reli\Command\Inspector\GetTraceCommand::execute /home/sji/work/reli/src/Command/Inspector/GetTraceCommand.php:133 6 Symfony\Component\Console\Command\Command::run /home/sji/work/reli/vendor/symfony/console/Command/Command.php:291 7 Symfony\Component\Console\Application::doRunCommand /home/sji/work/reli/vendor/symfony/console/Application.php:979 8 Symfony\Component\Console\Application::doRun /home/sji/work/reli/vendor/symfony/console/Application.php:299 9 Symfony\Component\Console\Application::run /home/sji/work/reli/vendor/symfony/console/Application.php:171 10 <main> /home/sji/work/reli/reli:45 <press q to exit> ...
执行进程必须具有CAP_SYS_PTRACE功能。(通常以root用户运行就足够了。)
守护进程模式
$ sudo php ./reli i:daemon -P "^/usr/sbin/httpd"
执行进程必须具有CAP_SYS_PTRACE功能。(通常以root用户运行就足够了。)
获取EG的地址
$ sudo php ./reli i:eg -p 2183131 0x555ae7825d80
执行进程必须具有CAP_SYS_PTRACE功能。(通常以root用户运行就足够了。)
在跟踪中显示当前正在执行的指令
如果用户想要分析一个真正的CPU密集型应用程序,那么他或她不仅想知道哪个行是慢的,还要知道哪个指令是。在这种情况下,使用--template=phpspy_with_opcode
与inspector:trace
或inspector:daemon
。
$ sudo php ./reli i:trace --template=phpspy_with_opcode -p <pid of the target process or thread>
输出如下。
0 <VM>::ZEND_ASSIGN <VM>:-1
1 Mandelbrot::iterate /home/sji/work/test/mandelbrot.php:33:ZEND_ASSIGN
2 Mandelbrot::__construct /home/sji/work/test/mandelbrot.php:12:ZEND_DO_FCALL
3 <main> /home/sji/work/test/mandelbrot.php:45:ZEND_DO_FCALL
0 <VM>::ZEND_ASSIGN <VM>:-1
1 Mandelbrot::iterate /home/sji/work/test/mandelbrot.php:30:ZEND_ASSIGN
2 Mandelbrot::__construct /home/sji/work/test/mandelbrot.php:12:ZEND_DO_FCALL
3 <main> /home/sji/work/test/mandelbrot.php:45:ZEND_DO_FCALL
当前执行的指令成为调用堆栈的第一帧。因此,像火焰图这样的跟踪可视化可以显示指令的使用情况。
出于信息目的,执行指令也被添加到每个调用帧的末尾。除了第一帧外,ZEND_DO_FCALL等函数调用指令也应该出现在那里。
如果目标进程启用了JIT,则此信息可能略有不准确。
在Docker容器中使用并针对主机上的进程
$ docker pull reliforp/reli-prof $ docker run -it --security-opt="apparmor=unconfined" --cap-add=SYS_PTRACE --pid=host reliforp/reli-prof i:trace -p <pid of the target process or thread>
从跟踪生成火焰图
$ ./reli i:trace -o traces -- php ./vendor/bin/psalm.phar --no-cache $ ./reli c:flamegraph <traces >flame.svg $ google-chrome flame.svg
下面的火焰图可视化了psalm命令执行的跟踪。
从phpspy兼容的跟踪生成speedscope
格式
$ sudo php ./reli i:trace -p <pid of the target process or thread> >traces $ ./reli c:speedscope <traces >profile.speedscope.json $ speedscope profile.speedscope.json
见#101。
从phpspy兼容的跟踪生成callgrind格式输出,并使用kcachegrind进行可视化
$ ./reli c:callgrind <traces >callgrind.out $ kcachegrind callgrind.out
转储目标进程的内存使用情况
注意
不要将此命令的输出上传到互联网,因为它可能包含目标脚本的敏感信息!!!
警告
此功能处于实验阶段,可能不如其他功能稳定。输出的内容可能在不久的将来发生变化。
$ sudo php ./reli i:memory -p 2183131 >2183131.memory_dump.json $ cat 2183131.memory_dump.json | jq .summary
目前仅支持NTS目标。
输出如下。
[ { "zend_mm_heap_total": 10485760, "zend_mm_heap_usage": 7642504, "zend_mm_chunk_total": 10485760, "zend_mm_chunk_usage": 7642504, "zend_mm_huge_total": 0, "zend_mm_huge_usage": 0, "vm_stack_total": 262144, "vm_stack_usage": 8224, "compiler_arena_total": 917504, "compiler_arena_usage": 815480, "possible_allocation_overhead_total": 549645, "possible_array_overhead_total": 378768, "memory_get_usage": 8263440, "memory_get_real_usage": 12582912, "cached_chunks_size": 2097152, "heap_memory_analyzed_percentage": 92.48574443573136, "php_version": "v82" } ]
您还可以从转储中获取调用跟踪。
$ cat 2183131.memory_dump.json | jq '.context.call_frames[]|objects|.function_name' "time_nanosleep" "Reli\\Lib\\Loop\\LoopMiddleware\\NanoSleepMiddleware::invoke" "Reli\\Lib\\Loop\\LoopMiddleware\\KeyboardCancelMiddleware::invoke" "Reli\\Lib\\Loop\\LoopMiddleware\\RetryOnExceptionMiddleware::invoke" "Reli\\Lib\\Loop\\Loop::invoke" "Reli\\Command\\Inspector\\GetTraceCommand::execute" "Symfony\\Component\\Console\\Command\\Command::run" "Symfony\\Component\\Console\\Application::doRunCommand" "Symfony\\Component\\Console\\Application::doRun" "Symfony\\Component\\Console\\Application::run" ""
您还可以查看特定调用帧的局部变量内容。
$ cat 2183131.memory_dump.json | jq '.context.call_frames[]|objects|select(.function_name=="time_nanosleep")' { "#node_id": 1, "#type": "CallFrameContext", "function_name": "time_nanosleep", "local_variables": { "#node_id": 2, "#type": "CallFrameVariableTableContext", "$args_to_internal_function[0]": { "#node_id": 3, "#type": "ScalarValueContext", "value": 0 }, "$args_to_internal_function[1]": { "#node_id": 4, "#type": "ScalarValueContext", "value": 9743095 } } }
如果上下文引用了转储文件中的另一个位置,也可以使用jq
提取。
$ cat 2183131.memory_dump.json | jq '.context.call_frames["7"].local_variables' { "#node_id": 1433, "#type": "CallFrameVariableTableContext", "command": { "#reference_node_id": 368 }, "input": { "#reference_node_id": 1395 }, "output": { "#reference_node_id": 54 }, "helper": { "#reference_node_id": 591 }, "commandSignals": { "#reference_node_id": 69 } } $ cat 2183131.memory_dump.json | jq '..|objects|select(."#node_id"==368)|.' | head -n 20 { "#node_id": 368, "#type": "ObjectContext", "#locations": [ { "address": 139988652434432, "size": 472, "refcount": 6, "type_info": 3221409800, "class_name": "Reli\\Command\\Inspector\\GetTraceCommand" } ], "object_handlers": { "#reference_node_id": 7 }, "object_properties": { "#node_id": 369, "#type": "ObjectPropertiesContext", "php_globals_finder": { "#node_id": 370, "#type": "ObjectContext", "#locations": [ {
您还可以提取对特定对象的全部引用。
$ cat 2183131.memory_dump.json | jq 'path(..|objects|select(."#reference_node_id"==368 or ."#node_id"==368))|join(".")' "context.call_frames.1.this.chain.callable.closure.this_ptr" "context.call_frames.1.this.chain.callable.closure.this_ptr.application.commands.array_elements.inspector:trace.value" "context.call_frames.1.this.chain.callable.closure.this_ptr.application.runningCommand" "context.call_frames.5.this" "context.call_frames.6.this" "context.call_frames.7.local_variables.command" "context.call_frames.8.local_variables.command" "context.objects_store.285"
在这个例子中,记录在内存位置的对象引用计数为6。通过$obj->call()
调用方法将引用计数增加1,但$this->call()
不会增加引用计数。来自objects_store的引用也不会增加引用计数。因此,这里分析了所有6个引用。
有关更多信息,请参阅./docs/memory-profiler.md。
故障排除
我收到错误消息“php模块未找到”,无法获取跟踪!
如果您的PHP二进制文件使用非标准的二进制名称,该名称不以/php
结尾,请使用--php-regex
选项指定包含PHP解释器的可执行文件(或共享对象)的名称。
我认为跟踪不准确。
-S
选项将为您提供更好的结果。使用此选项将在每次采样时暂时停止目标进程的执行,但获取的跟踪将更准确。如果您在分析像基准测试程序这样的CPU密集型程序时不停止单元虚拟机的运行,您可能会误判瓶颈,因为您将错过更多快速转换且未被良好检测到的虚拟机状态。
从ZTS目标获取跟踪在Ubuntu 21.10或更高版本上不起作用。
请尝试指定--libpthread-regex="libc.so"
作为选项。
我无法在Amazon Linux 2上获取跟踪。
首先,尝试使用 cat /proc/
检查目标 PHP 进程的内存映射。如果第一个模块没有指示 PHP 可执行文件的地址,看起来像是一个匿名区域,请尝试指定选项 --php-regex="^$"
。
目标
我们希望通过这个项目实现以下5个目标。
- 能够密切观察正在运行的 PHP 脚本内部发生的事情。
- 为 PHP 程序员提供一个创建可自由定制的 PHP 分析器的框架。
- 作为 PHP 在 Web 之外使用的实验,因为 PHP 的最新改进(如 JIT 和 FFI)已经打开了大门。
- 为 PHP 程序员提供了解 PHP 内部实现的另一个入口。
- 创建一个对我来说编写起来有趣的程序。
许可协议
- MIT(主要是)
- tools/flamegraph/flamegraph.pl 是从 https://github.com/brendangregg/FlameGraph 复制的,并受 CDDL 1.0 许可。请参阅 tools/flamegraph/docs/cddl1.txt 和脚本的头部。
- 一些定义内部结构的 C 头文件是从 php-src 中提取的。它们受 Zend 引擎许可证或 PHP 许可证的许可。请参阅 src/Lib/PhpInternals/Headers。因此,这里是一些由 Zend 引擎许可证和 PHP 许可证要求的词。
This product includes the Zend Engine, freely available at
http://www.zend.com
This product includes PHP software, freely available from
<https://php.ac.cn/software/>
“Reli”这个名字是什么意思?
根据其功能,你可能自然会想到这个名字代表“Reverse Elephpantineer's Lovable Infrastructure”。但不幸的是,这不是真的。
“Reli”没有具体含义,尽管你可以自由地认为这个工具是可靠的、虔诚的、令人愉悦的,或者你喜欢的一切“reli”。
最初,这个工具的名称只是“php-profiler”。由于一个许可问题(#175),这个简单的美好名字不得不改变。
因此,我们对原始名称应用了一个随机选择的字符串操作函数。 strrev('php-profiler')
得到 'reliforp-php'
,它可以读作“reli for p(php)”。
因此,这个工具的名称现在是“Reli for PH*”。你也可以只称之为“Reli”。
另请参阅
- adsr/phpspy
- Reli 受 phpspy 的极大启发。