XHProf - PHP性能分析工具

简介: XHProf - PHP性能分析工具的安装使用

本文主要介绍:

  1. 在 CentOS7 中的安装 XHProf
  2. 配置 XHProf 的网页图形化界面
  3. XHProf 数据的获取和分析
  4. 优化举例
  5. XHProf 的实现原理
  6. 其他功能

简介

XHProf是一个轻量级的 PHP 性能分析工具,提供了图形化的界面展示性能参数和过程。

1. 在 CentOS7 中的安装 XHProf

#获取源码包
wget http://pecl.php.net/get/xhprof-2.3.8.tgz

tar xvf xhprof-2.3.8.tgz
cd xhprof/extension

#编译安装
/opt/remi/php74/root/usr/bin/phpize

./configure --with-php-config=/opt/remi/php74/root/usr/bin/php-config

make && make install
#配置 xhprof 的扩展及运行数据路径

vim /etc/opt/remi/php74/php.d/20-xhprof.ini

; Enable xhprof extension module
extension=xhprof.so

#储存 XHProf 运行数据的默认目录,默认值是 /tmp
xhprof.output_dir=/tmp/xhprof

#重启 php-fpm
systemctl restart php74-php-fpm

#检查是否安装成功
php -m | grep xhprof

2. 配置 XHProf 的网页图形化界面

# 将源码包中的lib和html文件夹复制到项目路径下
cp -r /root/xhprof-2.3.8/xhprof_html /wwwroot/xhprof/

cp -r /root/xhprof-2.3.8/xhprof_lib /wwwroot/xhprof/
#配置Nginx
server {
    listen 1025;
    server_name your_ip_or_domain;

    root /wwwroot/xhprof/xhprof_html;
    index index.php index.html index.htm;

    access_log /var/log/nginx/xhprof_access.log;
    error_log /var/log/nginx/xhprof_error.log;

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi.conf;
    }
}

#重新加载nginx配置
nginx -s reload

#访问你的IP或域名

2.1 可能的问题

2.1.1 failed to execute cmd \" dot -Tpng\"
#安装libpng
wget https://sourceforge.net/projects/libpng/files/libpng16/1.6.28/libpng-1.6.28.tar.gz/download
mv download libpng-1.6.28.tar.gz
tar -zxvf libpng-1.6.28.tar.gz
cd libpng-1.6.28
./configure 
make && make install

#安装Graphviz
wget http://www.graphviz.org/pub/graphviz/stable/SOURCES/graphviz-2.24.0.tar.gz 
tar -zxvf graphviz-2.24.0.tar.gz
cd graphviz-2.24.0
./configure
make && make install

#重启php-fpm
2.1.2 看不到数据文件
#确认配置目录 xhprof.output_dir 的权限,并且存在数据文件
chown -R www:www /tmp/xhprof

3. XHProf 数据的获取和分析

3.1 数据获取

#开启xhprof
xhprof_enable(XHPROF_FLAGS_NO_BUILTINS | XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY, []);

#停止性能分析,并返回此次运行的 xhprof 数据
$xhprof_data = xhprof_disable();

#将数据写入文件中
file_put_contents('/tmp/xhprof/' . uniqid() . '.xhprof', serialize($data));

3.2 数据分析

Incl.       表示Including(包含)的缩写
Excl.       表示Excluding(不包含)的缩写
Function Name:      函数名
Calls:              调用次数
Calls%:             调用次数的百分比
Incl. Wall Time:    包含子函数执行的所有花费时间。单位:微秒(下同)
Excl. Wall Time:    函数本身执行所花费的时间。
Incl. CPU:          包含子函数执行的所花费的CPU时间。
Excl. CPU:          函数本身执行所花费的CPU时间。
Incl.MemUse:        包含子函数执行的所占用的内存。单位:字节(下同)
Excl.MemUse:        函数本身执行所占用的内存。
Incl.PeakMemUse:    包含子函数执行,所占用内存的峰值。
Excl.PeakMemUse:    函数本身执行所占用内存的峰值。

即:

  • 包含子函数的程序执行时间、CPU时间和内存消耗
  • 函数本身的程序执行时间、CPU时间和内存消耗
  • 所占程序执行时间、CPU时间或者内存消耗的百分比

4. 优化举例

  • 找一个较慢的API的运行数据,打开执行报告(Run Report),按照函数本身执行时间(Excl. Wall Time),倒序排序。
  • 可以看到排在上面的就是占用时间最多的函数,点击函数名称进入该函数的调用关系表中,往父级函数(Parent function)或子级函数(Parent function)找到自己开发的函数。
  • 查看函数代码,找出可优化点,比如循环查数据库是否可改为批量查,sql 是否使用了索引等等。
  • 实施代码优化方案,比如代码结构,数据缓存,MySQL索引
  • 同理,根据内存排序,可以找到是否使用了 select * from table_name 这样的查询语句,改成获取具体的字段,也可以用Redis,ES等手段去优化。

5. XHProf 的实现原理

5.1 PHP 是如何加载第三方扩展的?

加载流程:

  1. 扩展会提供一个 get_module(void) 的方法拿到扩展的 zend_module_entry 结构体的定义
  2. 扩展被编译成so文件后,在php.ini文件中配置 xxx.so, 表示加载扩展
  3. php 启动的时候会读取 php.ini 文件,并做解析
  4. 在 Linux 下 通过 dlopen() 打开扩展的 xxx.so 库文件
  5. 通过系统的 dlsym() 获取动态库中 get_module() 函数的地址,执行每个扩展的 get_module 方法拿到 zend_module_entry 结构体
  6. 把zend_module_entry 结构体注册到php的 extension_lists 扩展列表中。extension_lists是一个链表,保存着根据php.ini中定义的extension=xxx.so取到的全部扩展名称,其中engine是zend扩展,functions为php扩展
    1. 在 php 的生命周期中执行各个扩展定义的 PHP_MINIT

5.2 如何收集性能数据的?

起始外部扩展就是相当于内核一个模块,都是 zend_module_entry 结构体。
收集性能数据的原理,就是在模块初始化的时候代理了这个,代理了这个编译和执行OPCODE 的函数,覆盖了一层,加了自己的处理,自己的处理就是C代码的执行时间和PHP申请堆内存的计算。

收集数据的过程其实针对函数嵌套调用递归收集的过程。在调用xhprof_enable方法时,会把默认的方法替换为xhprof的方法。

static void hp_begin(long level, long xhprof_flags)
{
    if (!hp_globals.enabled)
    {
        int hp_profile_flag = 1;

        hp_globals.enabled = 1;
        hp_globals.xhprof_flags = (uint32) xhprof_flags;

         /* Replace zend_compile with our proxy */
                 /* 处理加载PHP文件 */
                 /* 先把zend引擎默认处理方法保存到_zend_compile_file变量中。*/
        _zend_compile_file = zend_compile_file;
                /* 在把xhprof相对应的方法赋值给zend_compile_file。
                   这样,每次加载PHP文件时,就会执行xhprof相应的方法。*/
        zend_compile_file  = hp_compile_file;

        /* Replace zend_compile_string with our proxy */
                /* 处理eval代码的执行 */
        _zend_compile_string = zend_compile_string;
        zend_compile_string  = hp_compile_string;

        /*init the execute pointer*/
                /* 处理 函数方法的执行 */
        _zend_execute_ex = zend_execute_ex;
        zend_execute_ex  = hp_execute_ex;

        // .........
    }
}

/*那我们看下,hp_compile_file方法,又是如何实现的*/
ZEND_DLEXPORT zend_op_array* hp_compile_file(zend_file_handle *file_handle, int type)
{
    const char *filename;
    char *func;
    int len;
    zend_op_array *ret;
    int hp_profile_flag = 1;

    filename = hp_get_base_filename(file_handle->filename);
    len = sizeof("load") - 1 + strlen(filename) + 3;
    func = (char *) emalloc(len);
    snprintf(func, len, "load::%s", filename);

        //方法执行前记录当前各项性能如数,如cpu 内存等
    BEGIN_PROFILING(&hp_globals.entries, func, hp_profile_flag);
        //开始zend引擎相应的方法,加载文件
    ret = _zend_compile_file(file_handle, type);
    if (hp_globals.entries)
    {
                //加载文件完毕后,再次记录当前各项性能数据。以便以后计算差值。
        END_PROFILING(&hp_globals.entries, hp_profile_flag);
    }

    efree(func);
    return ret;

xhprof_enable开启的这一行解析成 OPCODE,然后执行之前代理的 hp_execute_ex 函数,初始化main节点,来存当前调用PHP函数的性能数据 ct wt mu pmu等数据。

在xhprof_enable 和 xhprof_disable 之前的PHP代码,每一行都会被翻译成OPCODE,都会执行hp_execute_ex 函数。

$xhprof_data = xhprof_disable();
结束收集数据,返回已经收集到的数据。

数据格式在内核里面是一个二级HASHTABLE,对应PHP是一个二维数组

这个结束过程是对应这之前xhprof_enable的执行过程,是对main虚拟的节点做回源处理。

xhprof_enable提供了三个常量,用于设置你是否需要统计PHP内置函数,都统计那些指标。
三个常量如下:

XHPROF_FLAGS_NO_BUILTINS
设置这个常量后,将不统计PHP内置函数。毕竟PHP的内置函数性能一般都不错。没必要再消耗性能去统计。所以,建议设置。

XHPROF_FLAGS_CPU
设置这个常量后,会统计进程占用CPU时间。由于CPU时间是通过调用系统调用getrusage获取,导致性能比较差。开启这个选项后,大概性能下降一半。因此,如果对cpu耗时不是特别敏感的情况下,建议不要启用这个选项。

XHPROF_FLAGS_MEMORY
设置这个常量后,将会统计内存占用情况。由于获取内存情况,使用的是zend_memory_usage和zend_memory_peak_usage,并不是系统调用。因此,对性能影响不大。如果需要对内存使用情况进行分析的情况下,可以开启。

6. 其他功能

非侵入式监控php应用性能

xhprof_lib/utils/xhprof_lib.php文件包含额外的库函数,可用于维护、汇总XHProf运行结果。

例如:

  • xhprof_aggregate_runs() :可用于多次XHProf运行结果汇总到一个单一的运行。这可以帮助您使用XHProf来建立一个全系统“的函数级别”的性能监测工具 。 例如,您可以在生产环境中定期抽样XHProf的数据,产生小时/日 级别的报告。
  • xhprof_prune_run() :汇总大量XHProf运行结果(特别是如果它们对应不同类型的程序)将可能导致callgraph规模变得太大。您可以使用xhprof_prune_run功 能来修剪的callgraph数据中只占总运行时间中很小比例的子树。
目录
相关文章
|
2月前
|
设计模式 数据库连接 PHP
PHP中的设计模式:提升代码的可维护性与扩展性在软件开发过程中,设计模式是开发者们经常用到的工具之一。它们提供了经过验证的解决方案,可以帮助我们解决常见的软件设计问题。本文将介绍PHP中常用的设计模式,以及如何利用这些模式来提高代码的可维护性和扩展性。我们将从基础的设计模式入手,逐步深入到更复杂的应用场景。通过实际案例分析,读者可以更好地理解如何在PHP开发中应用这些设计模式,从而写出更加高效、灵活和易于维护的代码。
本文探讨了PHP中常用的设计模式及其在实际项目中的应用。内容涵盖设计模式的基本概念、分类和具体使用场景,重点介绍了单例模式、工厂模式和观察者模式等常见模式。通过具体的代码示例,展示了如何在PHP项目中有效利用设计模式来提升代码的可维护性和扩展性。文章还讨论了设计模式的选择原则和注意事项,帮助开发者在不同情境下做出最佳决策。
|
4天前
|
缓存 监控 Linux
Linux性能分析利器:全面掌握perf工具
【10月更文挑战第18天】 在Linux系统中,性能分析是确保软件运行效率的关键步骤。`perf`工具,作为Linux内核自带的性能分析工具,为开发者提供了强大的性能监控和分析能力。本文将全面介绍`perf`工具的使用,帮助你成为性能优化的高手。
26 1
|
4天前
|
缓存 监控 Linux
掌握Linux性能分析:深入探索perf工具
【10月更文挑战第26天】
11 1
|
17天前
|
敏捷开发 存储 数据可视化
解锁团队高效秘诀:5款顶尖PHP任务管理工具推荐
在现代企业中,高效的任务管理系统已成为不可或缺的工具,特别是在团队协作和项目管理中。PHP任务管理系统因其灵活性、开源性和易用性,备受企业管理者、项目团队和开发人员青睐。本文将介绍什么是PHP任务管理系统,其应用场景,以及推荐5款顶级的PHP任务管理系统,帮助企业提升效率和管理能力。
34 2
|
28天前
|
Web App开发 监控 JavaScript
一些常用的 Vue 性能分析工具
【10月更文挑战第2天】
53 1
|
2月前
|
SQL 缓存 关系型数据库
MySQL高级篇——性能分析工具
MySQL的慢查询日志,用来记录在MySQL中响应时间超过阀值的语句,具体指运行时间超过long-query_time值的SQL,则会被记录到慢查询日志中。long_query_time的默认值为 10,意思是运行10秒以上(不含10秒)的语句,认为是超出了我们的最大忍耐时间值。它的主要作用是,帮助我们发现那些执行时间特别长的 SOL 查询,并且有针对性地进行优化,从而提高系统的整体效率。当我们的数据库服务器发生阻塞、运行变慢的时候,检查一下慢查询日志,找到那些慢查询,对解决问题很有帮助。
MySQL高级篇——性能分析工具
|
2月前
|
设计模式 算法 PHP
PHP中的设计模式:策略模式的深入探索与实践在软件开发的广袤天地中,PHP以其独特的魅力和强大的功能,成为无数开发者手中的得力工具。而在这条充满挑战与机遇的征途上,设计模式犹如一盏明灯,指引着我们穿越代码的迷雾,编写出更加高效、灵活且易于维护的程序。今天,就让我们聚焦于设计模式中的璀璨明珠——策略模式,深入探讨其在PHP中的实现方法及其实际应用价值。
策略模式,这一设计模式的核心在于它为软件设计带来了一种全新的视角和方法。它允许我们在运行时根据不同情况选择最适合的解决方案,从而极大地提高了程序的灵活性和可扩展性。在PHP这门广泛应用的编程语言中,策略模式同样大放异彩,为开发者们提供了丰富的创作空间。本文将从策略模式的基本概念入手,逐步深入到PHP中的实现细节,并通过一个具体的实例来展示其在实际项目中的应用效果。我们还将探讨策略模式的优势以及在实际应用中可能遇到的挑战和解决方案,为PHP开发者提供一份宝贵的参考。
|
17天前
|
测试技术 PHP 开发工具
php性能监测模块XHProf安装与测试
【10月更文挑战第13天】php性能监测模块XHProf安装与测试
16 0
|
2月前
|
监控 IDE Java
【Java性能调优新工具】JDK 22性能分析器:深度剖析,优化无死角!
【9月更文挑战第9天】JDK 22中的性能分析器为Java应用的性能调优提供了强大的支持。通过深度集成、全面监控、精细化分析和灵活报告生成等核心优势,性能分析器帮助开发者实现了对应用性能的全面掌控和深度优化。在未来的Java开发过程中,我们期待性能分析器能够继续发挥重要作用,为Java应用的性能提升贡献更多力量。
|
6月前
|
监控 Java 开发者
Java一分钟之-Java性能分析与调优:JProfiler, VisualVM等工具
【5月更文挑战第21天】本文介绍了Java性能优化的两个利器——JProfiler和VisualVM。JProfiler通过CPU Profiler、内存分析器和线程视图帮助解决过度CPU使用、内存泄漏和线程阻塞问题;VisualVM则聚焦于GC行为调整和类加载优化,以减少内存压力和提高应用性能。使用这些工具进行定期性能检查,是提升Java应用效率的关键。
168 0