php使用reli分析性能,生成php性能火焰图-kb88凯时官网登录

来自:网络
时间:2024-06-09
阅读:
免费资源网,https://freexyz.cn/

reli 是一个用php编写的采样分析器(或vm状态检查器)。它可以从进程外部读取有关运行php脚本的信息。它是一个独立的cli工具,因此目标程序不需要任何修改。

能做什么?

  • 检测和可视化php脚本中的瓶颈。它不仅提供函数级的分析,而且还提供行级或操作码级的解析
  • 即使调用了很多快速函数,也不会产生累积开销的分析,因为这是一个采样分析器
  • 调查bug或性能故障的原因。即使php脚本处于无法解释的无响应状态,您也可以使用它来找出它在内部做什么。
  • 查找内存瓶颈或内存泄漏

如何工作?

  • 解析解释器的elf二进制文件
  • 从 /proc//maps读取内存映射
  • 通过ffi使用ptrace(2)和process_vm_readv(2)来读取外部进程的内存
  • 分析php虚拟机(又名zend engine)中的内部数据结构

需求

  • php 8.1 (nts/zts)
  • 64bit linux x86_64
  • 必须启用ffi扩展(编译增加配置--with-ffi)
  • 必须启用pcntl扩展

安装

git clone git@github.com:reliforp/reli-prof.git
cd reli-prof
/usr/local/php-8.2.14/bin/php /home/www/build/composer.phar install
/usr/local/php-8.2.14/bin/php ./reli

使用

1、获取跟踪配置

www@shaobowan:~/build/reli-prof$ /usr/local/php-8.2.14/bin/php ./reli inspector:trace --help
description:
  periodically get call trace from an outer process or thread
usage:
  inspector:trace [options] [--] [ [...]]
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

2、守护模式启动

www@shaobowan:~/build/reli-prof$ /usr/local/php-8.2.14/bin/php ./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

案例

这里跟踪一个webman框架进程

www@shaobowan:~/build/webman01$ php start.php status
workerman[start.php] status 
----------------------------------------------global status----------------------------------------------------
workerman version:4.0.37          php version:8.0.7
start time:2024-01-01 00:19:33   run 0 days 0 hours   
load average: 0.07, 0.12, 0.98   event-loop:\workerman\events\event
2 workers       3 processes
worker_name  exit_status      exit_count
webman       0                0
monitor      0                0
----------------------------------------------process status---------------------------------------------------
pid memory  listening           worker_name  connections send_fail timers  total_request qps    status
2184553 0.65m   http://0.0.0.0:8787 webman       0           0         0       0             0      [idle]
2184554 0.65m   http://0.0.0.0:8787 webman       0           0         0       0             0      [idle]
2184555 0.57m   none                monitor      0           0         1       0             0      [idle]
----------------------------------------------process status---------------------------------------------------
summary 0m      -                   -            0           0         1       0             0      [summary]

1、跟踪脚本

/usr/local/php-8.2.14/bin/php ./reli i:trace -- php -r "fgets(stdin);"
0 fgets :-1
1 
command line code:1 0 fgets :-1 1
command line code:1 ...

2、附加到正在运行的进程

sudo /usr/local/php-8.2.14/bin/php ./reli i:trace -p 2184553
[sudo] password for www: 
0 eventbase::loop :-1
1 workerman\events\event::loop /home/www/build/webman01/vendor/workerman/workerman/events/event.php:193
2 workerman\worker::run /home/www/build/webman01/vendor/workerman/workerman/worker.php:2435
3 workerman\worker::forkoneworkerforlinux /home/www/build/webman01/vendor/workerman/workerman/worker.php:1555
4 workerman\worker::forkworkersforlinux /home/www/build/webman01/vendor/workerman/workerman/worker.php:1397
5 workerman\worker::forkworkers /home/www/build/webman01/vendor/workerman/workerman/worker.php:1371
6 workerman\worker::runall /home/www/build/webman01/vendor/workerman/workerman/worker.php:549
7 
/home/www/build/webman01/start.php:112 ...

3、获取进程内存地址

sudo /usr/local/php-8.2.14/bin/php ./reli i:eg -p 2184553
0x55e17fe1b1a0

4、跟踪当前进程正在执行的操作码

如果用户想分析一个真正的cpu受限的应用程序,那么他或她不仅想知道哪一行是慢的,还想知道操作码是什么。在这种情况下,使用 --template=phpspy_with_opcode 与 inspector:trace 或 inspector:daemon 。

sudo /usr/local/php-8.2.14/bin/php ./reli i:trace --template=phpspy_with_opcode -p 2184553

输出如下所示

0 eventbase::loop :-1
1 workerman\events\event::loop /home/www/build/webman01/vendor/workerman/workerman/events/event.php:193:zend_do_fcall
2 workerman\worker::run /home/www/build/webman01/vendor/workerman/workerman/worker.php:2435:zend_do_fcall
3 workerman\worker::forkoneworkerforlinux /home/www/build/webman01/vendor/workerman/workerman/worker.php:1555:zend_do_fcall
4 workerman\worker::forkworkersforlinux /home/www/build/webman01/vendor/workerman/workerman/worker.php:1397:zend_do_fcall
5 workerman\worker::forkworkers /home/www/build/webman01/vendor/workerman/workerman/worker.php:1371:zend_do_fcall
6 workerman\worker::runall /home/www/build/webman01/vendor/workerman/workerman/worker.php:549:zend_do_fcall
7 
/home/www/build/webman01/start.php:112:zend_do_fcall ...

当前执行的操作码成为调用堆栈的第一帧。因此,像火焰图这样的可视化跟踪可以显示操作码的使用情况。

出于信息目的,执行操作码也被添加到调用帧的每一端。除了第一个帧,函数调用的操作码(如zend_do_fcall)应该出现在那里。如果在目标流程中启用了jit,则此信息可能会稍微不准确。

火焰图

火焰图是由 brendan gregg 发明的一种可视化方法,用于展示某一种系统资源或性能指标,是如何定量分布在目标软件里所有的代码路径上的。

  • 系统资源指标可以是 cpu 时间、off-cpu 时间、内存使用、硬盘使用、延时等任何其他你能想到的资源。
  • 代码路径 可以定义为目标软件代码中的调用栈轨迹。调用栈轨迹通常是由一组函数调用帧组成的,通常出现在 gdb 命令 bt 的输出中,以及 python 或 java 程序的异常错误信息当中。比如下面是一个 php 调用栈轨迹的样例:
c:ngx_http_lua_ngx_timer_at
at
cache.lua:43
cache.lua:record_timing
router.lua:338
router.lua:route
v2_routing.lua:1214
v2_routing.lua:route
access_by_lua.lua:130

1、psalm 静态检查

psalm 是一个用于php的开源静态分析工具,可以帮助识别代码中明显的和难以识别的bug。psalm既适用于大型遗留代码库,也适用于小型现代代码库,可以帮助防止绝大多数类型相关的runtime 错误,并且能够利用其他语言中流行的安全编码模式。psalm还可以自动修复发现的许多错误以改进代码。

cd /home/www/build/reli-prof
sudo /usr/local/php-8.2.14/bin/php ./reli i:trace -o traces -- /usr/local/php-8.2.14/bin/php ./vendor/bin/psalm.phar --no-cache
install the opcache extension to make use of jit on php 8.0  for a 20%  performance boost!
target php version: 8.1 (inferred from composer.json) enabled extensions: ffi.
scanning files...
analyzing files...
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  60 / 421 (14%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 120 / 421 (28%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 180 / 421 (42%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 240 / 421 (57%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 300 / 421 (71%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 360 / 421 (85%)
░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ 420 / 421 (99%)
░
------------------------------
                              
       no errors found!       
                              
------------------------------
checks took 7.42 seconds and used 134.539mb of memory
psalm was able to infer types for 99.9825% of the codebase

以上会输出一个traces文件,大概内容如下

0 array_merge :-1
1 psalm\internal\analyzer\statements\expression\simpletypeinferer::handlearrayitem phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/analyzer/statements/expression/simpletypeinferer.php:398
2 psalm\internal\analyzer\statements\expression\simpletypeinferer::inferarraytype phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/analyzer/statements/expression/simpletypeinferer.php:292
3 psalm\internal\analyzer\statements\expression\simpletypeinferer::infer phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/analyzer/statements/expression/simpletypeinferer.php:210
4 psalm\internal\phpvisitor\reflector\classlikenodescanner::visitclassconstdeclaration phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/phpvisitor/reflector/classlikenodescanner.php:760
5 psalm\internal\phpvisitor\reflector\classlikenodescanner::start phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/phpvisitor/reflector/classlikenodescanner.php:451
6 psalm\internal\phpvisitor\reflectorvisitor::enternode phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/phpvisitor/reflectorvisitor.php:116
7 _humbugbox427cd2d3980b\phpparser\nodetraverser::traversearray phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/vendor/nikic/php-parser/lib/phpparser/nodetraverser.php:176
8 _humbugbox427cd2d3980b\phpparser\nodetraverser::traversenode phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/vendor/nikic/php-parser/lib/phpparser/nodetraverser.php:105
9 _humbugbox427cd2d3980b\phpparser\nodetraverser::traversearray phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/vendor/nikic/php-parser/lib/phpparser/nodetraverser.php:196
10 _humbugbox427cd2d3980b\phpparser\nodetraverser::traverse phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/vendor/nikic/php-parser/lib/phpparser/nodetraverser.php:85
11 psalm\internal\scanner\filescanner::scan phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/scanner/filescanner.php:51
12 psalm\internal\codebase\scanner::scanfile phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/codebase/scanner.php:398
13 psalm\internal\codebase\scanner::scanapath phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/codebase/scanner.php:547
14 psalm\internal\codebase\scanner::scanfilepaths phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/codebase/scanner.php:310
15 psalm\internal\codebase\scanner::scanfiles phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/codebase/scanner.php:220
16 psalm\config::visitcomposerautoloadfiles phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/config.php:1840
17 psalm\internal\analyzer\projectanalyzer::visitautoloadfiles phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/analyzer/projectanalyzer.php:249
18 psalm\internal\analyzer\projectanalyzer::check phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/analyzer/projectanalyzer.php:335
19 psalm\internal\cli\psalm::run phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/src/psalm/internal/cli/psalm.php:272
20 
phar:///home/www/build/reli-prof/vendor/psalm/phar/psalm.phar/psalm:7 21
/home/www/build/reli-prof/vendor/psalm/phar/psalm.phar:14 22
/home/www/build/reli-prof/vendor/bin/psalm.phar:119

3、生成火焰图

sudo /usr/local/php-8.2.14/bin/php ./reli c:flamegraph <traces  >flame.svg
  • 1.

使用浏览器打开预览flame.svg 图片

下来生成一个webman的

workerman[start.php] status 
----------------------------------------------global status----------------------------------------------------
workerman version:4.1.9          php version:7.4.16
start time:2023-12-22 22:56:56   run 9 days 3 hours   
load average: 0.04, 0.03, 0.09   event-loop:\workerman\events\select
----------------------------------------------process status---------------------------------------------------
pid memory  listening           worker_name  connections send_fail timers  total_request qps    status
15456 16.42m  http://0.0.0.0:7788 webman       0           0         3       939           0      [idle]
----------------------------------------------process status---------------------------------------------------
summary 131m    -                   -            0           0         28      9191          0      [summary]

pid = 15456

sudo /usr/local/php-8.2.14/bin/php ./reli i:trace -p 15456 -o traces-15456 -- /usr/local/php-8.2.14/bin/php ./vendor/bin/psalm.phar --no-cache
sudo /usr/local/php-8.2.14/bin/php ./reli c:flamegraph flame-15456.svg

一个简单workerman火焰图到手啦!

其他

google-chrome安装(非必要)

下载

$ wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
--2023-12-31 10:43:53--  https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
resolving dl.google.com (dl.google.com)... 120.253.253.225
connecting to dl.google.com (dl.google.com)|120.253.253.225|:443... connected.
http request sent, awaiting response... 200 ok
length: 104953176 (100m) [application/x-debian-package]
saving to: ‘google-chrome-stable_current_amd64.deb'
google-chrome-stable_current_amd64.deb                  100%[==============================================================================================================================>] 100.09m  11.9mb/s    in 7.4s    
2023-12-31 10:44:00 (13.5 mb/s) - ‘google-chrome-stable_current_amd64.deb' saved [104953176/104953176]

安装

sudo apt install ./google-chrome-stable_current_amd64.deb

ffi

php编译安装启用ffi扩展(编译增加配置--with-ffi)时出现错误no package 'libffi' found,检查后发现是因为缺少libffi库文件,利用以下命令安装,解决问题:

sudo apt install libffi-dev

proc_open 无权限问题

php warning:  proc_open(): exec failed: permission denied in /home/www/build/reli-prof/src/command/converter/flamegraphcommand.php on line 44
php warning:  proc_open(): exec failed: permission denied in /home/www/build/reli-prof/src/command/converter/flamegraphcommand.php on line 55

赋予reli-prof目录执行权限

sudo chmod 0775 -r /home/www/build/reli-prof
免费资源网,https://freexyz.cn/
返回顶部
顶部
网站地图