如何衡量用PHP编写的代码的速度?

时间:2009-07-29 13:20:46

标签: php testing performance measurement

如何判断哪一类(哪些都做同样的工作)执行得更快?有没有可以衡量的软件?

10 个答案:

答案 0 :(得分:170)

你有(至少)两个解决方案:

非常“天真”的是在代码的一部分之前和之后使用microtime(true)来获取执行期间已经过了多少时间;其他答案已经说过,并且已经举了一些例子,所以我不会说更多。

如果您想要对几条指令进行基准测试,这是一个很好的解决方案;比如比较两种类型的函数 - 例如,如果做了几千次就更好了,以确保平均任何“扰动元素”。

这样的东西,所以,如果你想知道序列化数组需要多长时间:

$before = microtime(true);

for ($i=0 ; $i<100000 ; $i++) {
    serialize($list);
}

$after = microtime(true);
echo ($after-$before)/$i . " sec/serialize\n";

不完美,但有用,而且设置不需要太多时间。



如果你想确定哪个函数在整个脚本中花费了大量时间,那么另一个解决方案就是使用:

  • Xdebug扩展名,用于生成脚本的分析数据
  • 读取分析数据的软件,并为您提供可读的内容。我知道其中三个:
    • Webgrind;网络界面;应该适用于任何Apache + PHP服务器
    • WinCacheGrind;仅在Windows上
    • KCacheGrind;可能只有Linux和Linux一样;那是我喜欢的那个,顺便说一句

要获取分析文件,您必须安装和配置Xdebug;请查看文档的Profiling PHP Scripts页面。

我通常做的是默认情况下不启用探查器(它生成相当大的文件,并减慢速度),但可以使用发送名为XDEBUG_PROFILE的参数作为GET的可能性数据,仅为我需要的页面激活分析。
我的php.ini中与profiling相关的部分如下所示:

xdebug.profiler_enable = 0              ; Profiling not activated by default
xdebug.profiler_enable_trigger = 1      ; Profiling activated when requested by the GET parameter
xdebug.profiler_output_dir = /tmp/ouput_directory
xdebug.profiler_output_name = files_names

(阅读文档了解更多信息)

此屏幕截图来自KcacheGrind中的C ++程序:http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif
(来源:sourceforge.net

你会用PHP脚本得到完全相同的东西;-)
(使用KCacheGrind,我的意思是; WinCacheGrind不如KCacheGrind好......)

这使您可以很好地了解应用程序中需要花费时间的内容 - 它有时肯定有助于找到减慢所有内容的 功能^^

请注意,Xdebug计算PHP花费的CPU时间;当PHP等待数据库的答案时(例如),它无法正常工作;只有等待。所以Xdebug会认为DB请求不会花费太多时间!
这应该在SQL服务器上进行分析,而不是PHP,所以......


希望这有用:-)
玩得开心!

答案 1 :(得分:37)

对于快速的东西,我这样做(在PHP中):

$startTime = microtime(true);
doTask(); // whatever you want to time
echo "Time:  " . number_format(( microtime(true) - $startTime), 4) . " Seconds\n";

您还可以使用http://xdebug.org/等分析器。

答案 2 :(得分:8)

我做了一个简单的计时课程,也许对某人有用:

class TimingHelper {

    private $start;

    public function __construct() {
        $this->start = microtime(true);
    }

    public function start() {
        $this->start = microtime(true);
    }

    public function segs() {
        return microtime(true) - $this->start;
    }

    public function time() {
        $segs = $this->segs();
        $days = floor($segs / 86400);
        $segs -= $days * 86400;
        $hours = floor($segs / 3600);
        $segs -= $hours * 3600;
        $mins = floor($segs / 60);
        $segs -= $mins * 60;
        $microsegs = ($segs - floor($segs)) * 1000;
        $segs = floor($segs);

        return 
            (empty($days) ? "" : $days . "d ") . 
            (empty($hours) ? "" : $hours . "h ") . 
            (empty($mins) ? "" : $mins . "m ") . 
            $segs . "s " .
            $microsegs . "ms";
    }

}

使用:

$th = new TimingHelper();
<..code being mesured..>
echo $th->time();
$th->start(); // if it's the case
<..code being mesured..>
echo $th->time();

// result: 4d 17h 34m 57s 0.00095367431640625ms 

答案 3 :(得分:8)

以下是您问题的直接答案

  

有没有可以衡量的软件?

是的,有。我想知道为什么有人还没有提到它。虽然上面提到的答案似乎很适合快速检查,但从长远来看或者对于更大的项目来说是不可扩展的。

为什么不使用专门为此构建的应用程序性能监视(APM)工具以及更多内容。查看NewRelic,AppDynamics,Ruxit(都有免费版本)来监控每个应用程序的执行时间,资源使用情况,吞吐量到方法级别。

答案 4 :(得分:4)

我最近一直在使用XHProf http://pecl.php.net/package/xhprof。它最初是由Facebook开发的,它带有一个像样的网络界面。

答案 5 :(得分:4)

如果您想快速测试框架的性能,可以输入 index.php 文件

//at beginning
$milliseconds = round(microtime(true) * 1000);

//and at the end
echo round(microtime(true) * 1000) - $milliseconds;

每次您将以毫秒获得执行时间。因为微秒在测试框架案例时不太有用。

答案 6 :(得分:3)

我想与您分享一个自制功能,用于测量任何现有功能的速度,最多可达10个参数:

function fdump($f_name='', $f_args=array()){

    $f_dump=array();
    $f_result='';

    $f_success=false;

    $f_start=microtime();
    $f_start=explode(' ', $f_start);
    $f_start=$f_start[1] + $f_start[0];

    if(function_exists($f_name)){

        if(isset($f_args[0])&&is_array($f_args[0])){
            if($f_result=$f_name($f_args)){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[1])){
            if($f_result=$f_name($f_args[0])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[2])){
            if($f_result=$f_name($f_args[0],$f_args[1])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[3])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[4])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[5])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[6])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[7])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[8])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[9])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[10])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8],$f_args[9])){
                $f_success=true;
            }
        }
    }
    $f_end=microtime();
    $f_end=explode(' ', $f_end);
    $f_end=$f_end[1] + $f_end[0];

    $f_time=round(($f_end - $f_start), 4);
    $f_dump['f_success']=$f_success;
    $f_dump['f_time']=$f_time;
    $f_dump['f_result']=$f_result;

    var_dump($f_dump);exit;

    //return $f_result;

}

示例

function do_stuff($arg1='', $arg2=''){
    return $arg1.' '.$arg2;
}

fdump('do_stuff',array('hello', 'world'));

返回

  array(3) {
    ["f_success"]=>
    bool(true)
    ["f_time"]=>
    float(0)            //too fast...
    ["f_result"]=>
    string(11) "hello world"
  }

答案 7 :(得分:2)

如果它可以在Web上下文之外进行测试,我只需使用Unix time命令。

答案 8 :(得分:2)

Zend Studio内置了对使用XDebug或ZendDebugger进行性能分析的支持。它将描述您的代码,告诉您每个函数的确切时间。这是一个很好的工具,可以找出你的瓶颈所在。

答案 9 :(得分:0)

您可以在操作之前和之后使用基本内容来存储时间戳或microtime()来计算所需的时间。这很容易做到,但不是很准确。也许更好的解决方案是Xdebug,我从未使用它,但它似乎是我能找到的最着名的PHP调试器/分析器。