reliforp/reli-prof

PHP的一个采样分析器或内存分析器,使用PHP编写,可以从进程外部读取运行中的PHP虚拟机信息。

安装: 444

依赖关系: 0

建议者: 0

安全性: 0

星标: 455

关注者: 8

分支: 15

开放问题: 50

类型:项目

0.11.4 2024-02-07 13:36 UTC

README

Minimum PHP version: 8.1.0 Packagist Github Actions Scrutinizer Code Quality Coverage Status Psalm coverage

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_opcodeinspector:traceinspector: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命令执行的跟踪。

flame

从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//maps 检查目标 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”。

另请参阅