威尼斯手机平台登陆-官方网站登录

威尼斯手机平台登陆为您带来世界三大博彩公司最新相关资讯,威尼斯官方网站登录充分考虑到不同地域网民的不同需求,威尼斯手机平台登陆良好的用户界面,人性化的操作,实用的功能设计使其广泛受到欢迎,推动实体出版、影视、动漫、游戏等相关文化产业的发展。

您的位置:威尼斯手机平台登陆 > 最新文章 > Xdebug是一个开放源代码的PHP程序调试器,希望借助这个工具我们可以起到简单分析php程序性能瓶颈的问题

Xdebug是一个开放源代码的PHP程序调试器,希望借助这个工具我们可以起到简单分析php程序性能瓶颈的问题

发布时间:2020-04-21 16:06编辑:最新文章浏览(117)

    1. 关于代码覆盖率

    衡量代码覆盖率有很多种层次,比如行覆盖率,函数/方法覆盖率,类覆盖率,分支覆盖率等等。代码覆盖率也是衡量测试质量的一个重要标准,对于黑盒测试来说,如果你不确定自己的测试用例是否真正跑过了系统里面的每一行代码,在测试的完整性上总要打些折扣。因此,业界几乎对各种编程语言都有自己的一套代码覆盖率解决方案。世界上最美的语言PHP当然也不例外。PHPUnit和Spike PHPCoverage提供了一套基于xdebug的代码覆盖率测试方案。在本文中,我将针对自己碰到的特定业务场景,讲述一下自己进行PHP代码函数覆盖率测试的解决方案。

    PHP前端开发中的性能那点事

     在我们平时的php开发中,一个大的项目经过长时间的积累以后你会发现性能越来越慢,而性能到底消耗在了什么地方,常常是一个令人头疼的问题,function a()调用了多少次,function b()又消耗了多少时间,我们到底怎么查找是哪个蛀虫拉慢了我们的程序运行速度呢?在这里给大家介绍一款工具xdebug,相信很多人已经听说过了,希望借助这个工具我们可以起到简单分析php程序性能瓶颈的问题。

    A)假设1,假设用户目录在/home/ad
    B)假设2,假设php目录在/home/ad/php

    1、xdebug简介与安装
    Xdebug是一个开放源代码的PHP程序调试器(即一个Debug工具),可以用来跟踪,调试和分析PHP程序的运行状况。
    1)下载xdebug
    xdebug的官方下载地址为:
    最新版本为:Xdebug 2.1.0
    2)xdebug的安装

    1

    2

    3

    4

    5

    6

    7

    8

    cd /home/ad

    wget  http://xdebug.org/files/xdebug-2.1.0.tgz

    tar -zxvf xdebug-2.1.0.tgz

    cd xdebug-2.1.0

    /home/ad/php/bin/phpize

    ./configure --enable-xdebug --with-php-config=/home/ad/php/bin/php-config

    make

    make install

    安装完以后会提示你扩展安装到了哪个目录,类似  /home/ad/php/lib/php/extensions/no-debug-non-zts-20060613/
    假设你的php.ini放在 /home/ad/php/lib/php.ini
    加上

    1

    2

    3

    4

    5

    6

    7

    8

    9

    [xdebug]

    zend_extension = "/home/ad/php/lib/php/extensions/no-debug-non-zts-20060613/xdebug.so"

    xdebug.auto_trace = on

    xdebug.auto_profile = on

    xdebug.collect_params = on

    xdebug.collect_return = on

    xdebug.profiler_enable = on

    xdebug.trace_output_dir = "/home/ad/xdebug_log"

    xdebug.profiler_output_dir = "/home/ad/xdebug_log"

    重启apache
    去/home/ad/xdebug_log下看看是不是日志已经出来了

    2、xdebug参数简介
    zend_extension 加载xdebug扩展
    xdebug.auto_trace 自动打开打开函数调用监测
    xdebug.auto_profile 自动打开性能监测
    xdebug.trace_output_dir 设定函数调用监测信息的输出文件的路径。
    xdebug.profiler_output_dir 设定效能监测信息输出文件的路径。
    xdebug.collect_params 打开收集“函数参数”的功能。将函数调用的参数值列入函数过程调用的监测信息中。
    xdebug.collect_return 打开收集“函数返回值”的功能。将函数的返回值列入函数过程调用的监测信息中。

    3、示例程序与日志收集

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    <?php

    function a()

    {

        echo "aaa";   

    }

    function b()

    {

        a();

        sleep(1);

        a();

        sleep(1);

        a();   

    }

    b();

    ?>

     

     

    4、日志分析工具wincachegrind

    不用安装直接双击就可以打开了
    我们用它打开刚才收集的日志cachegrind.out.***

     

    前端开发中的性能那点事(二)巧用curl 并发减少后端访问时间

    前言:
    在我们平时的程序中难免出现同时访问几个接口的情况,平时我们用curl进行访问的时候,一般都是单个、顺序访问,假如有3个接口,每个接口耗时500毫秒那么我们三个接口就要花费1500毫秒了,这个问题太头疼了严重影响了页面访问速度,有没有可能并发访问来提高速度呢?今天就简单的说一下,利用curl并发来提高页面访问速度,
    希望大家多指导。
    1、老的curl访问方式以及耗时统计

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    <?php

    function curl_fetch($url, $timeout=3){

        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL, $url);

        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout);

        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        $data = curl_exec($ch);

        $errno = curl_errno($ch);

        if ($errno>0) {

            $data = false;

        }

        curl_close($ch);

        return $data;

    }

    function microtime_float()

    {

       list($usec, $sec) = explode(" ", microtime());

       return ((float)$usec + (float)$sec);

    }

    $url_arr=array(

         "taobao"=>"http://www.taobao.com",

         "sohu"=>"http://www.sohu.com",

         "sina"=>"http://www.sina.com.cn",

         );

     $time_start = microtime_float();

     $data=array();

     foreach ($url_arr as $key=>$val)

     {

         $data[$key]=curl_fetch($val);

     }

     $time_end = microtime_float();

     $time = $time_end - $time_start;

     echo "耗时:{$time}";

    ?>

    耗时:0.614秒
    2、curl并发访问方式以及耗时统计

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    <?php

    function curl_multi_fetch($urlarr=array()){

        $result=$res=$ch=array();

        $nch = 0;

        $mh = curl_multi_init();

        foreach ($urlarr as $nk => $url) {

            $timeout=2;

            $ch[$nch] = curl_init();

            curl_setopt_array($ch[$nch], array(

            CURLOPT_URL => $url,

            CURLOPT_HEADER => false,

            CURLOPT_RETURNTRANSFER => true,

            CURLOPT_TIMEOUT => $timeout,

            ));

            curl_multi_add_handle($mh, $ch[$nch]);

            ++$nch;

        }

        /* wait for performing request */

        do {

            $mrc = curl_multi_exec($mh, $running);

        } while (CURLM_CALL_MULTI_PERFORM == $mrc);

      

        while ($running && $mrc == CURLM_OK) {

            // wait for network

            if (curl_multi_select($mh, 0.5) > -1) {

                // pull in new data;

                do {

                    $mrc = curl_multi_exec($mh, $running);

                } while (CURLM_CALL_MULTI_PERFORM == $mrc);

            }

        }

      

        if ($mrc != CURLM_OK) {

            error_log("CURL Data Error");

        }

      

        /* get data */

        $nch = 0;

        foreach ($urlarr as $moudle=>$node) {

            if (($err = curl_error($ch[$nch])) == '') {

                $res[$nch]=curl_multi_getcontent($ch[$nch]);

                $result[$moudle]=$res[$nch];

            }

            else

            {

                error_log("curl error");

            }

            curl_multi_remove_handle($mh,$ch[$nch]);

            curl_close($ch[$nch]);

            ++$nch;

        }

        curl_multi_close($mh);

        return  $result;

    }

    $url_arr=array(

         "taobao"=>"http://www.taobao.com",

         "sohu"=>"http://www.sohu.com",

         "sina"=>"http://www.sina.com.cn",

         );

    function microtime_float()

    {

       list($usec, $sec) = explode(" ", microtime());

       return ((float)$usec + (float)$sec);

    }

    $time_start = microtime_float();

    $data=curl_multi_fetch($url_arr);

    $time_end = microtime_float();

    $time = $time_end - $time_start;

     echo "耗时:{$time}";

    ?>

     

     

    耗时:0.316秒
    帅气吧整个页面访问后端接口的时间节省了一半
    3、curl相关参数
    来自:
    curl_close — Close a cURL session
    curl_copy_handle — Copy a cURL handle along with all of its preferences
    curl_errno — Return the last error number
    curl_error — Return a string containing the last error for the current session
    curl_exec — Perform a cURL session
    curl_getinfo — Get information regarding a specific transfer
    curl_init — Initialize a cURL session
    curl_multi_add_handle — Add a normal cURL handle to a cURL multi handle
    curl_multi_close — Close a set of cURL handles
    curl_multi_exec — Run the sub-connections of the current cURL handle
    curl_multi_getcontent — Return the content of a cURL handle if CURLOPT_RETURNTRANSFER is set
    curl_multi_info_read — Get information about the current transfers
    curl_multi_init — Returns a new cURL multi handle
    curl_multi_remove_handle — Remove a multi handle from a set of cURL handles
    curl_multi_select — Wait for activity on any curl_multi connection
    curl_setopt_array — Set multiple options for a cURL transfer
    curl_setopt — Set an option for a cURL transfer
    curl_version — Gets cURL version information

    前端开发中的性能那点事(三)php的opcode缓存

     

    前言:由php的运行机制决定,其实php在运行阶段我们也是可以进行缓存的从而提高程序运行效率,这就是我们常说的opcode缓存。
    1、简述php的运行机制
    (因为本文是写opcode缓存的所以这里只是简要概述,后边会专门写一篇揭秘php运行机制的。)
    a).php文件通过浏览器过来
    b)请求交给SAPI,随后SAPI层将控制权转给PHP
    c)zend_language_scanner对代码进行扫描,对php代码进行词法分析转换成一系列的tokens array
    d)zend_language_parser将c步骤产生的一系列tokens处理掉空格等无用的代码以后转换成一系列表达式
    e)经过compiler阶段生成opcode返回zend_op_array指针
    f)zend_vm_execute根据传入的zend_op_array指针,执行opcode并将结果返回输出

    威尼斯正规官网 1

    2、opcode简介
    Opcode是operation code(操作码)的简称,其实就是第一小节c)、d)、e)步骤产生的一种中间码,
    opcode是一个四元组,(opcode, op1, op2, result),它们分别代表操作码,第一操作数,第二操作数,结果。
    如:

    1

    2

    3

    <?php

    echo "taobao search blog";

    ?>

    对应的tokens

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    Array

    (

        [0] => Array

            (

                [0] => 367

                [1] => <?php

                [2] => 1

            )

      

        [1] => Array

            (

                [0] => 316

                [1] => echo

                [2] => 1

            )

      

        [2] => Array

            (

                [0] => 370

                [1] =>

                [2] => 1

            )

      

        [3] => Array

            (

                [0] => 315

                [1] => "taobao search blog"

                [2] => 1

            )

      

        [4] => ;

        [5] => Array

            (

                [0] => 370

                [1] =>

                [2] => 1

            )

      

        [6] => Array

            (

                [0] => 369

                [1] => ?>

                [2] => 1

            )

      

    )

    对应的opcode就是

    1

    2

    3

    4

    5

    line     # *  op                           fetch          ext  return  operands

    ---------------------------------------------------------------------------------

       2     0  >   ECHO                                                     'taobao+search+blog'

       4     1    > RETURN                                                   1

             2*   > ZEND_HANDLE_EXCEPTION

    3、使用apc对opcode缓存
    a)假设php路径为/home/ad/php
    对opcode进行缓存的软件很多(apc、eAcclerator、Xcache、Zend Platform),这里主要介绍apc
    APC提供两种缓存功能,即缓存Opcode(目标文件),我们称之为apc_compiler_cache。同时它还提供一些接口用于PHP开发人员将用户数据驻留在内存中,我们称之为apc_user_cache。我们这里主要讨论apc_compiler_cache的配置。
    下载地址:
    最新版本为APC-3.1.6.tgz

    1

    2

    3

    4

    5

    6

    7

    wget http://pecl.php.net/get/APC-3.1.6.tgz

    tar -zxvf APC-3.1.6.tgz

    cd APC-3.1.6

    /home/ad/php/bin/phpize

    ./configure --enable-apc --enable-apc-mmap  --with-php-config=/home/ad/php/bin/php-config

    make

    make install

    编辑php.ini
    添加apc的配置

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    [apc]

    extension=apc.so

    apc.enabled=1

    apc.shm_segments = 1

    apc.shm_size = 128

    apc.ttl = 0

    apc.user_ttl = 7200

    apc.num_files_hint = 1000

    apc.write_lock=1

    apc.stat = 0

    apc.max_file_size=1M

    apc.filters = a.php,b.php

    apc.cache_by_default=1

    重新apache就ok啦

    4、常用参数的解析
    apc.enabled 开启apc 设置为0关闭,1为开启
    威尼斯正规官网,apc.shm_segments 共享内存块数
    apc.shm_size 共享内存大小,但是是M
    那么显然共享内存的总数就是apc.shm_segments*apc.shm_size
    apc.num_files_hint 允许多少个opcode被缓存
    apc.stat 为1的时候会自动检查opcode对应的php文件是否有更新,有更新的话会自动更新。设置为0的话就不会去检查了这样会提高apc的效率,但是要使php的修改生效的话就必须重启apache了,或者使用函数apc_cache_clear()来清空缓存
    apc.ttl opcode缓存的过期时间,设置为0表示不过期,如果不为0会检查两次请求之间的时间,如果时间大于设置值那么会更新opcode缓存
    apc.write_lock 表示多个进程同时更新一份opcode缓存的时候那么只让最先的一个生效,可以有效避免写冲突
    apc.max_file_size 超过设置值大小的文件不被缓存
    apc.filters 需要特例的文件,多个文件用逗号(,)相隔
    apc.filters 与 apc.cache_by_default结合使用,
    当apc.cache_by_default为1时apc.filters文件不被缓存,当apc.cache_by_default为0时仅apc.filters文件被缓存

    在我们平时的php开发中,一个大的项目经过长时间的积累以后你会发现性能越来越慢,而性能到底消耗在了什么...

    为什么需要Debugger?很多PHP程序员调试使用echo、print_r等,其实对 于有较丰富开发经验的程序员来说这些也已经足够了,他们往往可以在程序执行的过程中,通过输出特定变量的值可以判断程序执行是否正确,甚至效率高低也可以 看出来。那么我们为什么还需要一个专门的调试程序来监控我们的程序运行呢? 这个问题的答案不妨留到后面来揭晓。什么是Xdebug?Xdebug是一个开放源代码的PHP程序调试器,可以用来跟踪,调试和分析PHP程序的运行状况。如何安装Xdebug?:1. 打开 binaries版本 Linux:source得到一个dll文件2. 安装Win:将下载的dll文件放到相应的目录中。比如我的就放D:xamppphpext下面;Linux:执行安装文件tar -xvzf xdebug-2.1.2.tgzcd xdebug-2.1.2phpize (如果phpize没有这个command,需要安装一次phpize。phpize可以让php支持扩展模块)安装phpize:sudo apt-get install php5-dev如果安装了继续进行下面命令./configuremakemake install会有这个界面

    2. 业务背景

    假设我们在线开发了一个网站,交给业务测试的同事去进行功能测试。那他们是怎么测试的呢?通常情况下,无非是开发人员把网站部署好了,然后测试人员把网上所有功能都试用一遍,包括一些异常使用情况。对于业务测试来说,只要我把所有的功能点都测了,把所有异常使用情况也测到了,那就完成了。但是对于开发来说,我比较好奇的是,你是否把我写的所有代码都跑到了?会不会存在一些代码,只有在很特殊的情况下才能触发,而你从来没有测到过这些情况?这时,可能就需要代码覆盖率来出马了。

    其实我首先想到了xdebug来测试覆盖率,只需要两三个函数即可,如下:

    xdebug_start_code_coverage(); //开始收集代码行覆盖情况
    
    xdebug_get_code_coverage(); //获取截至目前所跑过的代码文件名和行号
    
    xdebug_stop_code_coverage(); //停止收集代码行覆盖情况
    

    xdebug提供的接口可以用于测试行覆盖率,这是否能满足要求呢?其实,行覆盖率颗粒度有点细,实际项目中,开发人员可能会对代码进行微调。比如,这次测试,你跑过了A.php文件的第10行,但是我有一天对A.php进行了微调,在A.php第9行和第10行之间又加了两行代码。于是,原来的第10行变为了第12行,而xdebug的行覆盖信息只记录了行号……这样之前的数据岂不是不准确了么。。。考虑再三,我觉得函数覆盖是个不错的颗粒度。在相对成熟的项目中,很少有大规模函数变动的情况。不过问题是,xdebug并没有提供函数覆盖的接口。

    于是,我们现在碰到的场景是:

    【1】希望测到某次测试中所覆盖的所有函数列表,知道这个项目总共有多少个函数,计算一下覆盖率是否足够高。

    【2】测试完成之后,要生成一份覆盖率报告,将代码的覆盖情况可视化。

    【3】完整测试的流程如下:

    威尼斯正规官网 2

    其中插桩的意思是在测试执行之前的一些准备工作。

    相关文章

    相关搜索:

    今天看啥

    搜索技术库

    返回首页

    • Xdebug配置
    • phpstudy 2013经常启动失败怎么办?
    • PHP文件上传类型后辍名对应mine对照表
    • 利用php函数获取爱站和chinaz百度权重的方法
    • 利用php函数自动获取alexa世界排名数据方法
    • php生成HTML文件的应用和原理笔记

    相关频道: PHP教程  WEB编程教程  Jsp教程  Python教程  Asp.Net教程  Ruby教程  ASP教程  PHP函数  

    cp modules/xdebug.so /usr/lib/php5/20090626+lfs 将xdebug.so文件移到php5下面3. 编辑php.ini,加入下面几行:[Xdebug]zend_extension=D:xamppphpextphp_xdebug.dll zend_extension=/usr/lib/php5/20090626+lfs/xdebug.soxdebug.profiler_enable=onxdebug.trace_output_dir="../Projects/xdebug"xdebug.profiler_output_dir="../Projects/xdebug"后面的目录“../Projects/xdebug”为你想要放置Xdebug输出的数据文件的目录,可自由设置。4. 重启Apache;5. 写一个test.php,内容为,如果输出的内容中有看到xdebug,说明安装配置成功。如下图:

    3. 函数覆盖率解决方案

    (1)原理

    xdebug天生提供了对行覆盖率的支持,我们要自己计算出函数覆盖率。函数覆盖率需要两点数据,一个是哪些函数被执行,一个是文件中总共有多少个函数。

    文件中总共的函数量,由于我们不可能把所有函数都执行一遍,因此这部分只能通过代码静态扫描来实现。如果是在C++或者Java中,可能就需要词法分析工具了,然而在最美的语言PHP面前,我们完全不需要那么复杂。从PHP4.3开始,PHP Zend Engine中内置了tokenizer功能,帮助开发者做源码词法分析。我们只需要找到PHP中定义函数时所对应的词法规律,就可以轻松得到指定PHP文件中的全部函数了。

    tokenizer定义的接口也十分简单:

    array token_get_all (string $source)
    

    该函数进行文件解析,将php源代码拆成由token组成的数组。

    string token_name (int $token)
    

    将整数形式的token转变为字符串形式。类似于C语言中的strerror函数。有了tokenizer,自己再根据php函数定义的规律和格式设计一个有限状态机,即可完成全量函数的解析。这部分代码,本人写了个比较简陋的,把它单独拿出来,仅供大家参考:PHPFunctionParser

    求函数覆盖率的另外一个难点在于获取被执行的函数列表。这地方让我们走了一些弯路。一开始一个最简单的办法,我们既然通过xdebug拿到被执的行,可以通过行号来反推此行属于哪一个函数。然而每一次的请求获取的行号信息量是非常大的,如果一个求情执行了1000行,那就要进行1000次判断,效率上会比较差。调研了一番之后,发现xdebug提供了function trace的功能,可以把一次请求中的函数调用关系获取到,只不过拿到了函数名字,却没办法得到它所在的文件。于是,再次调研一番,发现了Reflection,给定方法名和类名,可以反推出来它在哪个文件中定义。于是我们使用function trace把函数调用关系暂存在一个临时文件中,然后通过文件解析,拿到执行的函数名(如果是类方法,则是“类名::函数名”的形式),再通过reflection机制反推出定义这个函数的文件即可。再次体会到了世界上最美语言的强大之处。

    (2)插桩

    为了降低使用门槛,我们尽可能少地改变PHP源代码为好。xdebug收集信息的原理是分别调用xdebug_start_code_coverage和xdebug_stop_code_coverage来控制覆盖率信息收集的开始和结束,因此不可避免地要改变源代码。此处我们的解决办法是,将xdebug_stop_code_coverage通过register_shutdown_function注册为php程序结束前必须要跑的一段程序(类似C语言的atexit函数),将其封装到一个文件中,然后在源代码第一行require这个文件即可。如果你的PHP框架是CodeIgniter这种所有请求都有一个统一入口index.php的框架,那就只需要改变这一个文件即可,对源代码只有一行的改动!实际上,目前基本上所有的PHP框架,都是以一个index.php文件作为所有请求的入口。

    我们对源代码的改动只有入口文件index.php的第一行加入了一句话:

    require_once "/file/path/to/phpcoverage.php"; ?>
    

    而phpcoverage.php核心代码逻辑大致如下:

    <?php
     ……
    function xdebugPhpcoverageBeforeShutdown(){
     ……
     $lineCovData = xdebug_get_code_coverage();
     xdebug_stop_code_coverage();
     ……
     xdebug_stop_trace();
     ……
    }
    register_shutdown_function(‘xdebugPhpcoverageBeforeShutdown’);
    ……
    xdebug_start_trace(……);
    xdebug_start_code_coverage();
    //备注:上面省略号表示非关键代码,这里就不展示了
    

    (3)信息存储

    我们的函数覆盖率测试有了思路,使用xdebug的function trace获取一次请求中所有函数的调用关系,得到执行过的所有函数,输出到文件中,通过文件解析和reflection获得被执行的函数名和该函数所在文件。将这些信息存入数据库或文件即可。

    之前试用Spike的时候,我们发现这些信息以xml格式存入文件,数据冗余度很高,导致几个测试下来,文件已经非常大了。这显然不是我们想看到的。因此在数据存储的时候,我们直接将数据做json格式的序列化,字符串形式存在文件中,大大减少了文件大小。与此同时,我们再通过请求来源的IP和日期作为分隔,分别存储不同的文件。这样,来自每个机器每天的请求数据都能一目了然,向着“精准”的方向又迈进了一步,可以对测试人员的每个请求做精确的监控。下图是我们在业务实践中搜集的部分数据文件截图:

    威尼斯正规官网 3

    这样,来自任何一个IP的每一次Web请求,它所覆盖的行和函数信息,都会被记录到文件中。对于一般的项目测试中,也就只有几个测试人员在使用,所以不需要考虑一些性能问题。

    帮客评论

    现在我们来从最简单的程序调试开始一步步介绍Xdebug。调试:我们先写一个可以导致执行出错的程序,例如尝试包含一个不存在的文件。testXdebug.php然后通过浏览器访问,我们惊奇地发现,出错信息变成了彩色的了:

    4. 报告生成

    上面讲了生成覆盖率数据的原理,不过我们至此获得的只是一份份的数据文件,如何汇总成一份完整的报告呢?这就需要我们自己来写一段脚本解析刚才生成的数据文件了。我们的做法是借鉴了开源工具spike phpcoverage的模版,并加入自己的代码逻辑,特别是加入了该工具所不具有的函数覆盖率统计数据。我们自己测试的web页面生成的报告如下:

    威尼斯正规官网 4

    图中可以看到每个文件的行覆盖率,函数覆盖率,还有总的覆盖率统计数据。如果需要更精确的数据,可以点进文件连接,查看到底覆盖的是哪些代码行(蓝色为覆盖,红色为未覆盖):

    威尼斯正规官网 5

    不过除了样式改变,和我们平时打印的出错信息内容没什么不同,意义不大。好,我们继续改写程序:testXdebug2.php输出信息:

    5. 总结

    业务测试中做Web测试时,对代码的覆盖率是衡量测试质量的重要指标。我们希望通过此方法做到尽量地“精准”,测试执行完后可以精确看到哪一行代码被执行过,哪一行没被执行过。分析没被执行过的原因,从而改进测试用例。使用工具的流程也很简单,插桩=>测试=>搜集数据=>出报告。并且此解决方案最大化地减少了对业务代码的影响,只需要改一行代码即可。即便中间出现了问题,也可以快速将代码恢复为原来的样子。让测试放心,让开发也放心。

    不过,最后还需要强调的一点是,并不是说覆盖了所有的代码,就证明测试已经完整了。只不过没被覆盖的话,一定是不完整的。所以这个方案最大的意义在于能够发现测试中一些遗漏的代码,找到一部分问题。其实,它也可以帮助新来的员工理解整个项目代码结构,我们可以清晰的知道,自己的每一次浏览器请求,到底在运行服务器上的哪些代码。

    发现了什么? Xdebug跟踪代码的执行,找到了出错的函数testXdebug()。我们把代码再写得复杂一些: testXdebug3.php复制代码 代码如下:输出信息:

    也就是说Xdebug具有类似于Java的Exception的“跟踪回溯”的功能,可以根据程序的执行一步步跟踪到出错的具体位置,哪怕程序中的调用很复杂,我们也可以通过这个功能来理清代码关系,迅速定位,快速排错。

    其实PHP函数debug_backtrace()也有类似的功能,但是要注意debug_backtrace()函数只在PHP4.3.0之后版本及PHP5中才生效。这个函数是PHP开发团队在PHP5中新增的函数,然后又反向移植到PHP4.3中。

    如何利用Xdebug测试脚本执行时间测试某段脚本的执行时间,通常我们都需要用到microtime()函数来确定当前时间。例如PHP手册上的例子:复制代码 代码如下:但是microtime()返回的值是微秒数及绝对时间戳(例如“0.03520000 1153122275”),没有可读性。所以如上程序,我们需要另外写一个函数microtime_float(),来将两者相加。Xdebug自带了一个函数xdebug_time_index()来显示时间。如何测定脚本占用的内存?有时候我们想知道程序执行到某个特定阶段时到底占用了多大内存,为此PHP提供了函数memory_get_usage()。这个函数只有当PHP编译时使用了-enable-memory-limit参数时才有效。 Xdebug同样提供了一个函数xdebug_memory_usage()来实现这样的功能,另外xdebug还提供了一个xdebug_peak_memory_usage()函数来查看内存占用的峰值。

    如何检测代码中的不足?

    有时候代码没有明显的编写错误,没有显示任何错误信息(如error、warning、notice等),但是这不表明代码就是正确无误的。有时候可能某段代码执行时间过长,占用内存过多以致于影响整个系统的效率,我们没有办法直接看出来是哪部份代码出了问题。这时候我们希望把代码的每个阶段的运行情况都监控起来,写到日志文件中去,运行一段时间后再进行分析,找到问题所在。回忆一下,之前我们编辑php.ini文件加入[Xdebug]xdebug.profiler_enable=onxdebug.trace_output_dir="I:Projectsxdebug"xdebug.profiler_output_dir="I:Projectsxdebug"

    这几行,目的就在于把执行情况的分析文件写入到”../Projects/xdebug”目录中去。如果你执行某段程序后,再打开相应的目录,可以发现生成了一堆文件,例如cachegrind.out.1169585776这种格式命名的文件。这些就是Xdebug生成的分析文件。用编辑器打开你可以看到很多程序运行的相关细节信息,

    最后:

    Xdebug提供了各种自带的函数,并对已有的某些PHP函数进行覆写,可以方便地用于调试排错;Xdebug还可以跟踪程序的运行,通过对日志文件的分析,我们可以迅速找到程序运行的瓶颈所在,提高程序效率,从而提高整个系统的性能。

    本文由威尼斯手机平台登陆发布于最新文章,转载请注明出处:Xdebug是一个开放源代码的PHP程序调试器,希望借助这个工具我们可以起到简单分析php程序性能瓶颈的问题

    关键词:

上一篇:没有了

下一篇:而离线app必需是下载完离线缓存手艺使用