PHP性能检测工具介绍----XHProf

XHProf文件(草稿)

   

翻译:徐仁禄 <xurenlu [at] gmail.com >

原文地址:http://mirror.facebook.net/facebook/xhprof/doc.html

初次翻译,大部分是google translate tookit工具给翻的,稍微修改了下。如遇错误,还请来信指出。谢谢!

目录

  1. 导言
  2. XHProf 概况
  3. 安装XHProf扩展
  4. 使用XHProf进行性能分析
  5. 设置XHProf用户界面
  6. 在生产环境中使用XHProf注意事项
  7. 轻量级采样模式
  8. 附加功能
  9. 信赖
  10. 鸣谢
  1. 导言

XHProf是一个分层PHP性能分析工具。它报告函数级别的请求次数和各种指标,包括阻塞时间,CPU时间和内存使用情况。一个函数的开销,可细分成调用者和被调用者的开销。原始数据收集部分是用纯C实现的,是一个名叫xhprof的 Zend扩展。XHProf有一个简单的HTML的用户界面( PHP写成的)。基于浏览器的性能分析用户界面能更容易查看,或是与同行们分享成果。也能绘制调用关系图。

XHProf报告往往可以有助于理解被执行的代码的结构。的等级性质的报告可用来确定,例如,什么链要求导致了所谓的特殊功能得到。

XHProf可以比较两次运行的结果(又名“差异报告”)或是从多次运行得到的汇总数据。差异和汇总报告,就像单一运行报告一样,也提供“平板”以及“分层”的性能分析视图。

XHProf是一种轻量级的性能分析工具。在数据收集阶段,它记录调用次数的追踪和包容性的指标弧在动态 callgraph的一个程序。它独有的数据计算的报告/后处理阶段。在数据收集时,XHProfd通过检测循环来处理递归的函数调用,并通过给递归调用 中每个深度的调用一个有用的命名来避开死循环。

XHProf的轻量级性质和汇聚功能,使得它非常适合用于收集“生产环境”的性能统计数据的统计。[见用于生产环境的补充说明。 ]

例如,XHProfLive (不属于开源的工具包),是Facebook使用的一个全系统的性能监测系统,建立在XHProf的基础之上 。 XHProfLive不断收集函数级别的Profiler资料,这些资料来自生产环境中运行中的示例页面[用xhprof来收集] 。然后XHProfLive汇总指定的时候,页面类型,来取得各个页面的性能数据,可以帮助解决各种问题,如:特定的某个网页的函数级的性能情况怎样?在所有网页中,或者对某一具体的网页,foo 函数的开销如何?在过去的一小时/天/周中,哪些函数返回的次数最多?某个页面/函数的执行时间的变化趋势如何?等等。

由Facebook最初开发的XHProf在2009年3月开放源代码。

  1. XHProf概况

XHProf提供的功能:

    • 扁平的性能概要(截图 )

提供函数级别的性能信息,例如调用次数,其中包括/独家壁时间,内存使用情况,和CPU时间。

    • 分层剖析(父/子{0视图){/0} ( 截图 )

对每一个函数,它提供了一个断点,个崩溃的要求和时间每母公司(来电)和儿童(被调用) ,如:

      • 哪些函数调用了指定的函数,各自调了多少次?
      • 一个特定的函数调用了哪些函数?
      • 在被一个特定的函数调用时,某个函数一共耗去了多少时间 。
    • 差异报告

出于各种原因,您可能需要比较从两个XHProf运行中得到的数据-找出是什么造成了从一个版本到另一个版本的退步,或是评估您将要做的优化的性能提升。

阿差异报告考虑两分,作为输入,并提供两个平面功能级别差异的信息,和层次信息(细目差异的父母/儿童职能)的每个功能。

差异报告里的“平板”视图指出了最主要的退步或改进。

点击差异报告平板视图中的函数,进入“层次”(或父/子)视图。我们可以得到的具体的父子函数的差异。

    • Callgraph视图

性能数据也可以通过callgraph视图来查看 。callgraph 会高亮显示程序的关键路径。

    • 内存剖析

XHProf的内存剖析模式能有助于跟踪那些申请大量内存的函数。

值得澄清的是,XHProfu并不严格跟踪所有分配/释放内存的操作。相反,它使用了一种简化思路。他记录了每个函数进入和结束后的内存的增减。它还记录每个函数分配内存的峰值的变化。

    • XHProf记录include, include_once, require and require_once require_once操作,就像他们是函数一样。那些被包含文件的名字被用来产生假的函数的名字。
    • 术语表

1.        Inclusive Time (或子树执行时间) :[包括子树执行时间的所有执行时间。]

2.        Exclusive Time/Self Time :[函数执行本身的时间花费。]不包括子树执行时间。

3.        Wall时间 :又名经过的时间或挂钟时间。

4.        CPU时间 : CPU时间在用户空间+ CPU时间在内核空间

    • 特殊函数的命名约定

0.        main():一个虚构的函数,这是所有调用的根节点。

1.        load::<filename> 和 run_init::<filename>:

XHProf 跟踪PHP的include/require操作,和跟踪函数调用一样。

例如, include“lib/common.php"; 操作看起来像调了两个XHProf函数:

        • load::lib/common.php - 内核加载和编译文件的工作。[注:如果您使用的了PHP的opcode 缓存比如APC之类的,只有当缓存失效时才会去编译。
        • run_init::lib/common.php -由于包含操作引起的初始化操作等。

2.        foo@<n> :意味着这是一个foo()函数的递归调用。<n>代表递归深度。递归可能是直接的,(比如由于foo() -->foo() ) ,也可能是间接的(如由于foo()-> goo() ->foo()。

    • 限制

真正的层次剖析器会在每一个数据采集点记录完全的调用堆栈。接下来,能够回答这些问题,如:第三次foo()调用的开销是多少?或是当调用栈是a()->b()->bar()时bar()函数的开销是多少?

XHProf只记录一级的调用上下文,因此只能回答关于一级一级函数调用的问题。事实证明,在实践中这是最主要的利用情况。

为了使这个更具体,看看下面的例子。

假设你有:

 1call from a() --> c()

 1call from b() --> c()

 50calls from c() --> d()

虽然XHProf可以告诉你, d()被c()调用了50次,却不能告诉你,有多少次分别是由a()和b()引起的。[我们可以推测,也许有25次是因为a(),有25次是由于b(), 但未必如此。 ]

然而在实践中,这没什么大不了。

  1. 安装XHProf扩展

这个扩展在"extension"子目录里。

注:Windows的版本还没有实现。目前我们已经在Linux/FreeBSD 上测试了xhprof。

0.9.2及以上版本的XHProf也正计划着移植到Mac OS下。[我们在Mac OS 10.5下测试过。]

注: XHProf使用RDTSC指令(时间戳计数器)来实现一个真正的低资源消耗的计数器[针对elapsedtime]。因此目前xhprof还只适用于x86架构。此外,因为RDTSC的数据不能在CPU间同步,在剖析时xhprof会将程序绑定在单个的CPU。

如果SpeedStep技术是打开的,XHProf的基于RDTSC定时器的功能就不能正常工作了。这项技术在某些英特尔处理器上是可用的。[注:苹果台式机和笔记本电脑一般都将SpeedStep技术预设开启。使用XHProf,您需要禁用SpeedStep技术。 ]

下面的步骤,应该在Linux/ Unix环境下进行。

% cd<xhprof_source_directory>/extension/
% phpize
% ./configure --with-php-config=<path tophp-config >
% make
% make install
% make test


php.ini文件 :您可以更新您的php.ini文件来自动加载您的扩展。将以下内容添加到你的php.ini文件。

[xhprof]

extension=xhprof.so

;

; directory used by default implementationof the iXHProfRuns

; interface (namely, the XHProfRuns_Defaultclass) for storing

; XHProf runs.

;

xhprof.output_dir=<directory_for_storing_xhprof_runs>


  1.   使用XHProf来做性能分析

用下面的示例程序来试着产生一些原始的性能数据:

foo.php

<?php
function bar($x) {
  if($x > 0) {
     bar($x - 1);
  }
}

function foo() {
  for($idx = 0; $idx < 2; $idx++ ) {
      bar($idx);
      $x = strlen("abc");
  }
}

// start profiling

xhprof_enable();

// run program

foo();

// stop profiler

$xhprof_data = xhprof_disable();

// display raw xhprof data for the profilerrun

print_r($xhprof_data);
 

运行上面的测试程序:

% php -dextension=xhprof.so foo.php

你应该得到的输出如下:

Array
(
   [foo==>bar] => Array
       (
           [ct] => 2         # 2 calls tobar() from foo()
           [wt] => 27        # inclusivetime in bar() when called from foo()
       )

    [foo==>strlen]=> Array
       (
           [ct] => 2
           [wt] => 2
       )

   [bar==>bar@1] => Array    #a recursive call to bar()
       (
           [ct] => 1
           [wt] => 2
       )

   [main()==>foo] => Array
       (
           [ct] => 1
           [wt] => 74
       )

   [main()==>xhprof_disable] => Array
       (
           [ct] => 1
           [wt] => 0
       )

   [main()] => Array         #fake symbol representing root
       (
           [ct] => 1
           [wt] => 83
       )
)


注:The rawdata only contains "inclusive" metrics. For example, the wall timemetric in the raw data represents inclusive time in microsecs. Exclusive timesfor any function are computed during the analysis/reporting phase.

注意:默认情况下只有调用次数和占用时间是记录了的。您也可以选择同时记录CPU时间和/或单纯记录内存使用量。将下面这一行:

xhprof_enable();

换成:

xhprof_enable(XHPROF_FLAGS_CPU +XHPROF_FLAGS_MEMORY); ;

您应该得到如下的输出:

Array
(
   [foo==>bar] => Array
       (
           [ct] => 2        # number ofcalls to bar() from foo()
           [wt] => 37       # time inbar() when called from foo()
           [cpu] => 0       # cpu time inbar() when called from foo()
           [mu] => 2208     # change inPHP memory usage in bar() when called from foo()
           [pmu] => 0       # change in PHP peak memory usage in bar()when called from foo()
       )

   [foo==>strlen] => Array
       (
           [ct] => 2
           [wt] => 3
           [cpu] => 0
           [mu] => 624
           [pmu] => 0
       )

   [bar==>bar@1] => Array
       (
           [ct] => 1
           [wt] => 2
           [cpu] => 0
           [mu] => 856
           [pmu] => 0
       )

   [main()==>foo] => Array
       (
           [ct] => 1
           [wt] => 104
           [cpu] => 0
           [mu] => 4168
           [pmu] => 0
       )

   [main()==>xhprof_disable] => Array
       (
           [ct] => 1
           [wt] => 1
           [cpu] => 0
           [mu] => 344
           [pmu] => 0
       )

   [main()] => Array
       (
           [ct] => 1
           [wt] => 139
           [cpu] => 0
           [mu] => 5936
           [pmu] => 0
       )
)


在分析时跳过内置函数

默认情况下, PHP的内置函数(如strlen )也被分析了。如果您不希望分析内置函数(为了进一步减少性能分析的开销貌相或减小产生的原始数据) ,您可以使用XHPROF_FLAGS_NO_BUILTINS标 志,例如:

// do not profile builtin functionsxhprof_enable(XHPROF_FLAGS_NO_BUILTINS ) ;

在性能分析时忽略特定函数( 0.9.2或更高版本支持)

从0.9.2版本的xhprof ,你可以告诉XHProf在性能分析时忽略一些指定函数。这样,您就可以忽略,像功能用于间接函数调用,如call_user_func和call_user_func_array的函数 。这些不必要的中间层,因为他们乱七八糟的父-子关系和间接的互相调用,使XHProf报告难以理解。

要设定要忽略的函数列表,可以在分析时给xhprof_enable函数 指定第二个参数[是个可选参数] 。例如,

// elapsed time profiling; ignorecall_user_func* during profiling

xhprof_enable(0,
            array('ignored_functions' => array('call_user_func', 'call_user_func_array')));
or,
 
// elapsed time + memory profiling; ignorecall_user_func* during profiling
xhprof_enable(XHPROF_FLAGS_MEMORY,
              array('ignored_functions' =>array('call_user_func','call_user_func_array')));

  1. 设置XHProf用户界面

1.        PHP源码目录结构

XHProf的用户界面的由PHP实现。代码存放在两个子目录中:xhprof_html/和xhprof_lib/ 。

xhprof_html目录包含了3个顶级PHP页面。

      • index.php :查看一个单一运行或差异报告。
      • callgraph.php :以图片的形式查看一次XHProf运行的调用关系图。
      • typeahead.php :在XHProf的报告中被后台调用来进行函数的自动补全。

该xhprof_lib目录包含进行分析和显示的支持代码(计算 扁平的性能信息,计算diffs,从多次运行中汇总数据等等) 。

2.        Web服务器配置:您需要确保您的Web服务器有权限读取xhprof_html/目录可,并且能运行PHP脚本。

3.        管理XHProf运行

客户端能很灵活地保存他们从XHProf运行中得到的XHProf原始数据。用户界面层 的XHProf提供了一个iXHProfRuns接口(见xhprof_lib/ utils / xhprof_runs.php ),客户端可以利用。这使得客户端能够告诉用户界面层,如何获取XHProf运行后产生的对应数据。

XHProf的UI 库自带的有一个基于文件的iXHProfRUns接口实现,即“ XHProfRuns_Default”(见xhprof_lib/utils/xhprof_runs.php)。这个自带的实现将XHProf运行结果存在ini配置的xhprof.output_dir参数指定的某个目录下。

一次XHProf运行,必须用一个命名空间和运行编号来唯一确定。

一)XHProf数据的永久保存

假设您使用的iXHProfRuns接口的XHProfRuns_Default这个默认实现方式,一个典型的XHProf运行并保存结果的操作可能就是这样子的:

// start profiling

xhprof_enable();

 

// run program

....

 

// stop profiler

$xhprof_data = xhprof_disable();

 

//

// Saving the XHProf run

// using the default implementation ofiXHProfRuns.

//

include_once $XHPROF_ROOT ."/xhprof_lib/utils/xhprof_lib.php";

include_once $XHPROF_ROOT ."/xhprof_lib/utils/xhprof_runs.php";

 

$xhprof_runs = new XHProfRuns_Default();

 

// Save the run under a namespace"xhprof_foo".

//

// **NOTE**:

// By default save_run() will automaticallygenerate a unique

// run id for you. [You can override thatbehavior by passing

// a run id (optional arg) to thesave_run() method instead.]

//

$run_id =$xhprof_runs->save_run($xhprof_data, "xhprof_foo");

 

echo "---------------\n".

    "Assuming you have set up the http based UI for \n".

    "XHProf at some address, you can view run at \n".

    "http://<xhprof-ui-address >/index.php?run=$run_id&source=xhprof_foo\n".

    "---------------\n";


 

上述代码就会将运行结果保存在xhprof.output_dir ini参数指定的特定目录下。文件的名称可能会是49bafaa3a3f66.xhprof_foo类似的东东 ;两部分分别是运行编号( “ 49bafaa3a3f66 ” )和命名空间( “ xhprof_foo ” )。[如果您想创建/指定自己的run ID (如数据库中的序列号,或时间戳) ,您可以通过明确的给save_run方法指定一个run id。

b )使用自己实现的iXHProfRuns

如果您希望您的XHProf运行存储在不同的数据库(例如用一个压缩格式,或者其他什么地方比如数据库等),您需实现一个类,这个实必须实现iXHProfRuns ( )接口。

您还需要修改“xhprof_html/"目录中3个主要的PHP入口文件(index.php,callgraph.php ,typeahead.php ),使用新的类而不是默认的类XHProfRuns_Default。改变3个文件的这一行:

$xhprof_runs_impl = new XHProfRuns_Default();

您还需要“include”声明了上述class的文件。

4.        从用户界面中访问各次运行

一)看单一运行报告

要查看run id是<run_id>和命名空间是<namespace>的报告,访问URL:

http://<xhprof-ui-address>/index.php?run=<run_id>&source=<namespace>

例如,

http://<xhprof-ui-address>/index.php?run=49bafaa3a3f66&source=xhprof_foo

二)查看diff报告

要查看命名空间<namespace>下runid分别是< run_id1>和<run_id2>的两个报告,访问URL:

http://<xhprof-ui-address>/index.php?run1=<run_id1>&run2=<run_id2>&source=<namespace>

三)汇总报告

您也可以指定一组run id来汇总得到您想要的报告视图。

如果你有三个XHProf运行,都在"benchmark‘命名空间下,run id分别是1,2,3。要查看这些运行的汇总报告:

http://<xhprof-ui-address>/index.php?run=1,2,3&source=benchmark

加权汇总 :进一步假设,上述3个运特分别对应三种程序,p1.php,p2.php和p3.php ,通常以20%,30%,50%概率混合:要查看汇总报告所对应的加权平均数这些运行使用:

http://<xhprof-ui-address>/index.php?run=1,2,3&wts=20,30,50&source=benchmark

  1. 在生产环境中使用XHProf的注意事 项

这里给出一些意见和准则。您的情况可能会有所不同:

    • CPU的计时器( getrusage )在Linux上开销很大。为了在函数级别更有用,这个是粗粒度的(毫秒精确度,而不是微秒水平)。因此,使用XHPROF_FLAGS_CPU模式时,在报告里,数字上的误差往往会更高。

我们建议在生产环境中使用"占用时间+内存" 来做性能分析。[注:内存性能分析模式的额外开销很低。 ]

 

// elapsed time profiling (default) +memory profiling

 xhprof_enable(XHPROF_FLAGS_MEMORY);

    • 对随机抽样的部分page/request来做性能分析,对于获取您的生产环境的负载情况特征数据,其实足够好了了。

分析万分之一的请求,可以用下面的代码:

if (mt_rand(1, 10000) == 1) {

  xhprof_enable(XHPROF_FLAGS_MEMORY);

  $xhprof_on = true;

 }

request结束时(或是在退出函数中) ,您可以这么做:

 if($xhprof_on) {

   // stop profiler

  $xhprof_data = xhprof_disable();

 

   //save $xhprof_data somewhere (say a central DB)

  ...

 }


然后,您就可以用xhprof_aggregate_runs()来按时间(比如,每5分钟/每小时/每天),或是按页面类型/request类型来汇总。

  1. 轻量级采样模式

Xhprof扩展还提供了一个轻量级采样模式。采样间隔为0.1秒。采样记录了整个函数调用堆栈。如果想以增加极低的负载作代价来进行性能监控和诊断,采样模式就是你想要的。

XHProf扩展提供的与采样模式相关的函数有xhprof_sample_enable()xhprof_sample_disable()

[ 待定:关于采样模式更详细的文档。 ]

  1. 附加功能

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

例如:

    • xhprof_aggregate_runs() :可用于多次XHProf运行结果汇总到一个单一的运行。这可以帮助您使用XHProf来建立一个全系统“的函数级别”的性能监测工具 。 [例如,您可以在生产环境中定期抽样XHProf的数据,产生小时/日级别的报告。 ]
    • xhprof_prune_run() :汇总大量XHProf运行结果(特别是如果它们对应不同类型的程序)将可能导致callgraph规模变得太大。您可以使用xhprof_prune_run功 能来修剪的callgraph数据中只占总运行时间中很小比例的子树。
  1. 依赖性
    • JQuery的Javascript :在提示和函数名称补齐上 ,我们利用了JQuery这个JavaScript库。JQuery是基于MIT和GPL licencse ( http://docs.jquery.com/Licensing ) 的。XHProf用到的JQuery相关代码,在xhprof_html/jquery子 目录。
    • dot(图像生成工具) :调用关系视图工具( [查看Callgraph ] )这个功能依靠dot工具实现。 “点”是一种绘制/生成有向图的工具。
    • 鸣谢

查询分析结果的HTML用户界面受到了Oracle 的存储过程语言PL/SQL里的一个相似的小工具的启发。但是仅仅如此,他们的内部性能分析过程是完全不同的。


来源:百度文库http://wenku.baidu.com/view/14a5a1f7ba0d4a7302763a4e.html

你可能感兴趣的:(PHP性能检测工具介绍----XHProf)