200416-使用Xhprof查找PHP性能瓶颈

PHP性能分析——Xhprof

前言

你和别人同时写出了一个导出订单的功能,你的导出一次用了30分钟,别人用了1分钟,那么这里就很明显的区分出来了你们代码的效率。代码的优劣是问题的根源。如果你想找出是什么原因导致代码执行这么慢,那么你就要学会怎么分析代码性能,找到代码瓶颈。

安装Xhprof扩展

下载安装

1
2
3
4
5
6
7
8
wget http://pecl.php.net/get/xhprof-0.9.4.tgz
tar -zxvf xhprof-0.9.4.tgz
cd xhprof-0.9.4
cd extension/
phpize
./configure
make
sudo make install

配置修改

修改php.ini

1
2
3
[xhprof]
extension=xhprof.so
xhprof.output_dir=/tmp

配置中xhprof.output_dir指定了生成的profile文件存储的位置,我们将其指定为/tmp

对PHP进行性能分析

在XHProf扩展中,一共提供了四个函数用于对PHP进行性能分析。

  1. xhprof_enable/xhprof_sample_enable
    函数用于开始XHProf性能分析,区别在于前者功能更加强大,而后者则是是以简单模式启动性能分析(简单记录了函数的调用栈信息),开销比较小。

  2. xhprof_disable/xhprof_sample_disable函数用于停止性能分析,并返回分析的数据。

  3. 需要特别说明的函数是xhprof_enable,其他函数都是不需要提供参数的,而该函数则可以接受两个可选的参数,用于改变该工具的行为。

void xhprof_enable ([ int $flags = 0 [, array $options ]] )

  • flags 该参数用于为剖析结果添加额外的信息,该参数的值使用以下宏,如果需要提供多个值,使用|进行分隔。

XHPROFFLAGSNO_BUILTINS 跳过所有的内置函数
XHPROFFLAGSCPU 添加对CPU使用的分析
XHPROFFLAGSMEMORY 添加对内存使用的分析

  • options 数组形式提供可选参数,在此处提供ignored_functions选项需要忽略的函数

比如下面的例子,同时对内存和CPU进行分析,并且忽略对call_user_func和call_user_func_array函数的分析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
xhprof_enable(
XHPROF_FLAGS_MEMORY|XHPROF_FLAGS_CPU,
[
'ignored_functions' => [
'call_user_func',
'call_user_func_array'
]
]
);

// 这里是PHP代码,比如业务逻辑实现等要被分析的代码部分
....

$xhprofData = xhprof_disable();// $xhprofData是数组形式的分析结果
print_r($xhprofData);

注意,如果使用XHPROF_FLAGS_CPU选项对CPU占用也进行分析,在Linux环境下,会造成比较高的系统负载,因此不建议使用,而推荐只使用XHPROF_FLAGS_MEMORY,对内存的分析不会对系统造成太多负载。

图形化查看分析结果

使用xhprof_disable完成性能分析并且获取到分析结果之后,我们通常不会直接输出结果,因为这样的结果是以数组形式组织的,看起来并不直观,幸运的是,xhprof提供了基于web的图形界面对分析结果进行查看。

在使用之前,请先确保服务器安装了graphviz工具,否则在生成监控图表的时候回出现以下错误:

1
failed to execute cmd: " dot -Tpng". stderr: `sh: dot: command not found '

这里提示找不到dot命令,所以需要先安装graphviz

1
sudo yum install graphviz

由于分析结果的查看工具是基于web的,因此,我们需要将xhprof安装包中的xhprofhtml和xhproflib目录放到服务器的web目录下,让xhprof_html目录中的内容对外可以访问。

由于分析结果的查看工具是基于web的,因此,我们需要将xhprof安装包中的xhprofhtml和xhproflib目录放到服务器的web目录下,让xhprof_html目录中的内容对外可以访问。

1
2
3
4
[vagrant@localhost xhprof]$ pwd
/vagrant/xhprof
[vagrant@localhost xhprof]$ ls
xhprof_html xhprof_lib

web服务器使用的是Nginx,因此,在Nginx的配置文件nginx.conf中的配置如下:

1
2
3
4
5
server {
listen 80;
server_name _;
root /vagrant;
...

web服务器的根目录是/vagrant,因此访问地址为http://localhost/xhprof/xhprof_html/index.php

当然,配置好环境之后,我们还是获取不到分析结果的,因为我们在代码中并没有将分析结果保存到xhprof.output_dir指定的目录中。

分析结果

分析结果

注意到中间的View Full Callgraph链接,通过该链接我们可以看到图形化的分析结果。

图形化分析结果

图形化分析结果

图中红色的部分为性能比较低,耗时比较长的部分,我们可以根据根据哪些函数被标记为红色对系统的代码进行优化

概要报告字段含义

字段名称 含义
Function Name 方法名称
Calls 方法被调用的次数
Calls% 方法调用次数在同级方法总数调用次数中所占的百分比
Incl.Wall Time(microsec) 方法执行花费的时间,包括子方法的执行时间。(单位:微秒)
IWall% 方法执行花费的时间百分比
Excl. Wall Time(microsec) 方法本身执行花费的时间,不包括子方法的执行时间。(单位:微秒)
EWall% 方法本身执行花费的时间百分比
Incl. CPU(microsecs) 方法执行花费的CPU时间,包括子方法的执行时间。(单位:微秒)
ICpu% 方法执行花费的CPU时间百分比
Excl. CPU(microsec) 方法本身执行花费的CPU时间,不包括子方法的执行时间。(单位:微秒)
ECPU% 方法本身执行花费的CPU时间百分比
Incl.MemUse(bytes) 方法执行占用的内存,包括子方法执行占用的内存。(单位:字节)
IMemUse% 方法执行占用的内存百分比
Excl.MemUse(bytes) 方法执行占用的内存,包括子方法执行占用的内存。(单位:字节)
EMemUse% 方法本身执行占用的内存百分比
Incl.PeakMemUse(bytes) Incl.MemUse峰值。(单位:字节)
IPeakMemUse% Incl.MemUse峰值百分比
Excl.PeakMemUse(bytes) Excl.MemUse峰值。单位:(字节)
EPeakMemUse% Excl.MemUse峰值百分比

并且页面可以点击对应的头部指定排序方式

本文参考链接

# ,
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×