《让PHP扩展开拓编程前路》 之 性能分析利器 tideways

Ref

1、Intro

1.1 tideways 的发展

PHP 扩展 xhprof 是一个轻量级的分层性能测量分析器,最开始由 Facebook 开发 facebook/xhprof,用于分析和优化 PHP WEB 网站,在2009年开源,后来没跟上 PHP 的步伐,掉队 PHP7.x 系列,但 tideways 抓住了时机,紧随其后,对 xhprof 进行重写,推出 php-xhprof-extension 扩展。虽然 tideways 没有发布在 PECL,也没有在 PHP 官网 有相关说明,但有商业公司支持,并且积极支持 PHP7.x 系列,显然是受欢迎的。

tideways 其中有特点的几个版本v4.1.7 v5.x。 其中 v4.1.7,最高支持 PHP7.3 ,如果 PHP7.4 上无法使用该版本的 tideways,但是该版本有 SQL 分析功能,还是很有亮点的一部分,并且此时的 tideways 扩展名为 tideways.so ;但由于后续商业化,在 v5.x 时,更名为 tideways_xhprof.so 扩展,并且移除 SQL 分析功能;

  • tideways.so 开源版
    • php-xhprof-extensionv4.1.7 版本,最高支持 PHP7.3 版本,带有 SQL 分析功能;
  • tideways_xhprof.so 开源版
    • php-xhprof-extensionv5.x 版本,支持PHP7以上,当前也包括 PHP8,此版本移除 SQL 分析功能,基本的分析还是有的,比如 Callgraph, 而且此扩展还在更新;
  • tideways.so 商业版
    • 需要购买 tideways 产品,它将以 SAAS 方式更丰富的性能分析功能(本文不讨论商业版),但是仍然致敬,有商业支持的,才有精力开源,虽然丐版,但 tideways_xhprof.so 也够用;

1.2 xhgui 汉化的事情

xhgui 基于 Bootstrap 的 xhprof WEB UI ,当然原英文版 perftools/xhgui ,看起来确实没那么舒服,但还好有汉化版。感谢 @laynefyc,提供两款 UI ,分别是 基于 Bootstrap 的 laynefyc/xhgui-branch 和 基于 Vue 的 laynefyc/php-monitor

对于 Profiler 性能分析器来说, 不论是 xhprof 还是 tidewaystideways_xhprof 扩展,所采集的日志数据是可以通用的,你可以这么理解,虽然逻辑不太一样,但最终展示数据格式的一样的,所以像 xhgui 这样的 WEB UI 机会很灵活。你可以根据自己 PHP 的版本,来选择合适的 Profiler 扩展,但记住只需要启用任意一个扩展即可,再选择合适的 UI 展示。

  • 本文采用 php-monitor 来实现 WEB UI 展示;

1.3 采集数据存储的事情

通常来说 xhgui 会提供几种方式,比如 mongodb sqlite mysql 等,你可以根据自己情况来进行选择。本文采用 mongodb ,因此首先要确定 mongodb 的服务端,以及PHP的扩展;

  • 通常来说 Profiler 采集数据包括
    • 函数调用次数
    • 执行消耗的时间
    • CPU消耗的时间
    • 使用的内存
    • sql的执行
    • 函数调用图
    • 火焰图
    • 瀑布图

2、Prepare

2.1 我的环境

  • PHP 7.3.20 没有是最新的是因为我太懒,晚点换
[root@Centos7 ~]# php -v
PHP 7.3.20 (cli) (built: Jan 11 2021 17:21:40) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.3.20, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.3.20, Copyright (c) 1999-2018, by Zend Technologies

[root@Centos7 ~]# /php/php73/bin/pecl -V
PEAR Version: 1.10.12
PHP Version: 7.3.20
Zend Engine Version: 3.3.20
Running on: Linux Centos7 3.10.0-1160.11.1.el7.x86_64 #1 SMP Fri Dec 18 16:34:56 UTC 2020 x86_64

[root@Centos7 ~]# cat /etc/redhat-release 
CentOS Linux release 7.9.2009 (Core)

2.2 安装 tideways 扩展

  • 源码安装 tideways
    • 由于我的 PHP 是 7.3 版本,因此可以安装 tideways v4.x 的版本,这里采用 v4.1.7
[root@Centos7 phpext]# wget https://github.com/tideways/php-xhprof-extension/archive/v4.1.7.tar.gz 
[root@Centos7 phpext]# tar zxvf v4.1.7.tar.gz 
[root@Centos7 phpext]# cd php-xhprof-extension-4.1.7
[root@Centos7 php-xhprof-extension-4.1.7]# /php/php73/bin/phpize && ./configure --with-php-config=/php/php73/bin/php-config &&  make && make install

[root@Centos7 ~]# ll /php/php7.3.20/lib/php/extensions/no-debug-non-zts-20180731/tideways.so 
-rwxr-xr-x 1 root root 445120 May 18 19:08 /php/php7.3.20/lib/php/extensions/no-debug-non-zts-20180731/tideways.so


# 追加配置
[root@Centos7 php-xhprof-extension-4.1.7]# vim /php/php7.3.20/lib/php.ini
[tideways]
extension=tideways.so
;不需要自动加载,在程序中控制就行
tideways.auto_prepend_library=0
;频率设置为100,在程序调用时能改
tideways.sample_rate=100

# 重启 PHP
[root@Centos7 php-xhprof-extension-4.1.7]# /etc/init.d/php-fpm73 restart
Gracefully shutting down php-fpm . done
Starting php-fpm  done

# 检查 `tideways` 是否被加载
[root@Centos7 ~]# php -m | grep tideways 
tideways

[root@Centos7 ~]# php --ri  tideways

tideways

tideways => 4.1.7
Connection (tideways.connection) => unix:///var/run/tideways/tidewaysd.sock
UDP Connection (tideways.udp_connection) => 127.0.0.1:8135
Default API Key (tideways.api_key) =>  
Default Sample-Rate (tideways.sample_rate) => 100
Framework Detection (tideways.framework) =>  
Service Name (tideways.service) =>  
Automatically Start (tideways.auto_start) => Yes
Tideways Collect Mode (tideways.collect) => tracing
Tideways Monitoring Mode (tideways.monitor) => basic
CLI Monitoring enabled (tideways.monitor_cli) => 0
Timeout for talk to Daemon (tideways.timeout) => 10000
Allowed Distributed Tracing Hosts (tideways.distributed_tracing_hosts) => 127.0.0.1
Load PHP Library (tideways.auto_prepend_library) => No
Tideways.php found => No

2.3 安装 tideways_xhprof 扩展

  • 源码安装 tideways_xhprof
    • 由于我的 PHP 是 7.3 版本,因此可以安装 tideways v5.x 的版本,这里采用 v5.0.4
[root@Centos7 phpext]# wget https://github.com/tideways/php-xhprof-extension/releases/download/v5.0.4/tideways-xhprof-5.0.4-x86_64.tar.gz
[root@Centos7 phpext]# tar zxvf tideways-xhprof-5.0.4-x86_64.tar.gz
./
./tideways_xhprof-5.0.4/
./tideways_xhprof-5.0.4/tideways_xhprof-8.0.so
./tideways_xhprof-5.0.4/LICENSE
./tideways_xhprof-5.0.4/tideways_xhprof-7.3.so
./tideways_xhprof-5.0.4/tideways_xhprof-7.4-zts.so
./tideways_xhprof-5.0.4/tideways_xhprof-7.2.so
./tideways_xhprof-5.0.4/tideways_xhprof-7.0.so
./tideways_xhprof-5.0.4/tideways_xhprof-7.2-zts.so
./tideways_xhprof-5.0.4/tideways_xhprof-7.4.so
./tideways_xhprof-5.0.4/tideways_xhprof-7.1.so
./tideways_xhprof-5.0.4/tideways_xhprof-7.3-zts.so
./tideways_xhprof-5.0.4/NOTICE
./tideways_xhprof-5.0.4/tideways_xhprof-8.0-zts.so
./tideways_xhprof-5.0.4/tideways_xhprof-7.1-zts.so
[root@Centos7 phpext]# cd tideways_xhprof-5.0.4
[root@Centos7 tideways_xhprof-5.0.4]# cp tideways_xhprof-7.3.so /php/php7.3.20/lib/php/extensions/no-debug-non-zts-20180731/tideways_xhprof.so 


# 追加配置
[root@Centos7 php-xhprof-extension-4.1.7]# vim /php/php7.3.20/lib/php.ini
[tideways_xhprof]
extension=tideways_xhprof.so

# 重启 PHP
[root@Centos7 php-xhprof-extension-4.1.7]# /etc/init.d/php-fpm73 restart
Gracefully shutting down php-fpm . done
Starting php-fpm  done

# 检查 `tideways_xhprof` 是否被加载
[root@Centos7 ~]# php -m | grep tideways_xhprof 
tideways_xhprof

[root@Centos7 tideways_xhprof-5.0.4]# php --ri  tideways_xhprof

tideways_xhprof

Version => 5.0.4
Clock Source => clock_gettime


Tideways is a PHP Profiler, Monitoring and Exception Tracking Software.

The 'tideways_xhprof' extension provides a subset of the functionality of our commercial Tideways offering in a modern, optimized fork of the XHProf extension from Facebook as open-source. (c) Tideways GmbH 2014-2017, (c) Facebook 2009

Register for a free trial on https://tideways.io

3、Ues Profiler

3.0 准备工作

3.0.1 快速起一个 WEB 项目

可以找任意框架,或者你当前的项目,这里只是为了演示,用了这个仓库 PFC

[root@Centos7 php-xhprof]# pwd
/code/php-xhprof
# 克隆项目
[root@Centos7 php-xhprof]# git clone https://github.com/Tacks9/php-framework-by-composer pfc
[root@Centos7 php-xhprof]# ls pfc/
app  bootstrap.php  composer.json  composer.lock  composer.phar  config  data  public  readme.md  services  vendor

# 配置 Nginx
[root@Centos7 php-xhprof]# vim /etc/nginx/conf/pfc.conf
server
{
    listen 80;
    server_name pfc.tacks.com;

    index index.html index.htm index.php index.shtml index.shtm;
    root /code/php-xhprof/pfc/public;

    access_log /logs/tacks/pfc.tacks.com-access.log;
    error_log /logs/tacks/pfc.tacks.com-error.log;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SERVER_SOFTWARE nginx;
        include fastcgi_params;
    }
}
# 重启 Nginx
[root@Centos7 php-xhprof]# systemctl restart nginx

# 设置 hosts
[root@Centos7 php-xhprof]# vim /etc/hosts
127.0.0.1 pfc.tacks.com

# 模拟请求
[root@Centos7 php-xhprof]# curl http://pfc.tacks.com/home/echotest
<h1> 控制器、方法  Home/echotest </h1>

3.0.2 部署 xhgui 汉化版 php-monitor

# 克隆项目
[root@Centos7 php-xhprof]# git clone https://github.com/laynefyc/php-monitor monitor
[root@Centos7 monitor]# pwd
/code/php-xhprof/monitor
# composer 安装依赖
[root@Centos7 monitor]# composer install

[root@Centos7 monitor]# ls
composer.json  composer.lock  phpunit.xml  public  README.md  README-zh_CN.md  src  tests  vendor

# 配置 Nginx
[root@Centos7 monitor]# vim /etc/nginx/conf/monitor.conf
server
{
    listen 80;
    server_name monitor.tacks.com;

    index index.html index.htm index.php index.shtml index.shtm;
    root /code/php-xhprof/monitor/public;

    access_log /logs/tacks/monitor.tacks.com-access.log;
    error_log /logs/tacks/monitor.tacks.com-error.log;

    location / {
        try_files $uri $uri/ /index.php?$args;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SERVER_SOFTWARE nginx;
        include fastcgi_params;
    }
}
# 重启 Nginx
[root@Centos7 monitor]# systemctl restart nginx

# 配置 HOST
# 127.0.0.1 monitor.tacks.com

3.0.3 php-monitor 默认配置

  • src/config/config.php
    • debug 默认 false
    • extension 默认 tideways
      • xhprof
      • tideways_xhprof
    • save 存储默认 sqlite ,但无论那种方式存储,默认表名 php_monitor
      • mysql
      • mongodb
    • profiler 采集比例
    • user 登陆账号逻辑在 src/controller/LoginController.php
      • WEB UI 默认账号密码
<?php
return [
    'debug' => false,
    /*
     * support extension: uprofiler, tideways_xhprof, tideways, xhprof
     * default: tideways
     */
    'extension' => 'tideways',
    // 'save' => [
    //     'driver'    => 'mysql',
    //     'host'      => '127.0.0.1:3306',
    //     'database'  => 'php_monitor',
    //     'username'  => '',
    //     'password'  => 'abcd1234',
    //     'charset'   => 'utf8mb4',
    //    'options' => [
    //        1005 => 16777216, //PDO::MYSQL_ATTR_MAX_BUFFER_SIZE and 16M
    //    ]
    // ],
    //  'save' => [
    //      'driver'    => 'mongodb',
    //      'host'      => '127.0.0.1:27017',
    //      'database'  => 'php_monitor',
    //      'username'  => '',
    //      'password'  => ''
    //  ],
   'save' => [
       'driver'    => 'sqlite',
       'database'  =>  dirname(__DIR__).'/db/php_monitor.sqlite3'
   ],
    'profiler' => [
        'enable' => function() {
            return true;//rand(1, 100) > 0;
        },
        'filter_path' => [
            //filter the DOCUMENT_ROOT
            //'/home/www/xhgui/webroot','F:/phpPro'
        ]
    ],
    'user' => [
        //login account and password
        ['account'=>'php','password'=>'php'],
        ['account'=>'admin','password'=>'abcd']
    ]
];

PHP-Monitor-登陆页面

PHP-Monitor-登陆首页

3.0.4 php-monitor 源码修改,修复 profiler.enable 回调函数

  • src/common/PMonitor.php

if(!$config['profiler']['enable']

代码15行位置,修改为,否则无法过滤域名的作用

if(!$config['profiler']['enable']()

3.0.5 pfc.tacks.com WEB 项目 Nginx 配置修改

  • 增加一行 auto_prepend_file 设置,然后重启 Nginx
location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9001;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SERVER_SOFTWARE nginx;
        fastcgi_param PHP_VALUE "auto_prepend_file=/code/php-xhprof/monitor/src/autoPrepend.php";
        include fastcgi_params;
    }

3.0.6 pfc.tacks.com WEB 项目,新增 MySQL,导入 SQL 数据

  • 查看 pfc/data/pfc.sql ,新增 article 表, 以及录入数据

可以访问

  • http://pfc.tacks.com/home/recentList
  • http://pfc.tacks.com/home/article

3.0.7 php-monitor 设置 Mongodb 索引

[root@Centos7 monitor]# mongo

> show dbs
> use php_monitor // Please select your own database
> db.php_monitor.createIndex({"url":1})
> db.php_monitor.createIndex({"ip":1})

3.1 使用 tideways 搭配 php-monitor

3.1.1 调整 php-monitor 的配置

  • php 扩展
[root@Centos7 monitor]# php --ri tideways
tideways

tideways => 4.1.7
  • php.ini 的扩展配置
; 启用 mongodb
[mongodb]
extension=mongodb.so

; 启用 tideways
[tideways]
extension=tideways.so
tideways.auto_prepend_library=0
tideways.sample_rate=100

; 关闭 tideways_xhprof
;[tideways_xhprof]
;extension=tideways_xhprof.so
  • php-monitor 配置修改
    • extension 采用 tideways
    • save 采用 mongodb
    • profiler 收集 pfc.tacks.com 域名
    • user WEB UI 账号密码采用 php
<?php
return [
    'debug' => true,
    'extension' => 'tideways',
    'save' => [
         'driver'    => 'mongodb',
         'host'      => '127.0.0.1:27017',
         'database'  => 'php_monitor',
         'username'  => '',
         'password'  => ''
    ],
    'profiler' => [
        'enable' => function() {
            // return true;//rand(1, 100) === 42;
            if ($_SERVER['SERVER_NAME'] == 'pfc.tacks.com') {
                return true;
                // 100%采样,默认为1%
                return rand(1, 100) === 42;
            } else {
                return false;
            }
        },
        'filter_path' => [
            //filter the DOCUMENT_ROOT
            //'/home/www/xhgui/webroot','F:/phpPro'
        ]
    ],
    'user' => [
        ['account'=>'php','password'=>'php'],
    ]
];

3.1.2 php-monitor 监控首页

PHP-MONITOR-首页列表

3.1.3 php-monitor 请求URL折线图

  • 点击列表的 “请求URL” ,查看请求的折线图

PHP-MONITOR-点击某个URL请求-查看执行状态的折线图

3.1.4 php-monitor 请求详情页

  • 点击列表的“请求时间”

PHP-MONITOR-URL请求详情页-1

PHP-MONITOR-URL请求详情页-2

3.1.5 php-monitor 请求火焰图

PHP-MONITOR-URL请求火焰图

3.1.6 php-monitor SQL执行记录

PFC-文章列表

PFC-文章列表-请求折线图

PFC-文章列表-SQL执行记录

3.2 使用 tideways_xhprof 搭配 php-monitor

3.2.1 调整 php-monitor 的配置

  • php 扩展
[root@Centos7 monitor]# php --ri tideways_xhprof

tideways_xhprof

Version => 5.0.4
  • php.ini 的扩展配置,修改后重启 php
; 启用 mongodb
[mongodb]
extension=mongodb.so

; 关闭 tideways
;[tideways]
;extension=tideways.so
;tideways.auto_prepend_library=0
;tideways.sample_rate=100

; 开启 tideways_xhprof
[tideways_xhprof]
extension=tideways_xhprof.so
  • php-monitor 配置修改
    • extension 采用 tideways_xhprof
    • save 采用 mongodb
    • profiler 收集 pfc.tacks.com 域名
    • user WEB UI 账号密码采用 php
<?php
return [
    'debug' => true,
    'extension' => 'tideways_xhprof',
    'save' => [
         'driver'    => 'mongodb',
         'host'      => '127.0.0.1:27017',
         'database'  => 'php_monitor',
         'username'  => '',
         'password'  => ''
    ],
    'profiler' => [
        'enable' => function() {
            // return true;//rand(1, 100) === 42;
            if ($_SERVER['SERVER_NAME'] == 'pfc.tacks.com') {
                return true;
                // 100%采样,默认为1%
                return rand(1, 100) === 42;
            } else {
                return false;
            }
        },
        'filter_path' => [
            //filter the DOCUMENT_ROOT
            //'/home/www/xhgui/webroot','F:/phpPro'
        ]
    ],
    'user' => [
        ['account'=>'php','password'=>'php'],
    ]
];

3.2.2 php-monitor 监控器无法查看 SQL 执行记录

PFC-文章列表-SQL执行记录-无记录

3.2.3 php-monitor 监控器其他服务都正常

本作品采用《CC 协议》,转载必须注明作者和本文链接
明天我们吃什么 悲哀藏在现实中 Tacks
讨论数量: 4

支持swoole么

11个月前 评论
Tacks (楼主) 11个月前

我debian 安装一直/www/server/php/73/lib/php/extensions/no-debug-non-zts-20180731/tideways.so 报错 Segmentation fault

5个月前 评论
Tacks (楼主) 5个月前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!