如何测量用PHP编写的代码的速度?[关闭]


Answers:


195

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

相当“幼稚”的是在一部分代码之前和之后使用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-like; 我喜欢的就是那个,顺便说一句

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

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

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 ++程序:(来源:sourceforge.net使用PHP脚本将获得完全相同的结果 ;-)(使用KCacheGrind,我的意思是WinCacheGrind不如KCacheGrind。 )http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif



这使您可以很好地了解应用程序中所花的时间-有时可以明确地帮助定位使所有功能变慢函数^^

请注意,Xdebug会计算PHP花费的CPU时间。当PHP在等待数据库的答案时(例如),它不起作用;只等。因此Xdebug会认为数据库请求不会花费很多时间!
应该在SQL服务器而不是PHP上进行概要分析,因此...


希望这对
您有所帮助:-) 玩得开心!


1
QCacheGrind的窗户建设存在:-) sourceforge.net/projects/qcachegrindwin
弗朗索瓦·布雷顿

43

为了快速起见,我这样做(在PHP中):

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

您还可以使用http://xdebug.org/之类的探查器。


2
为了提高准确性,我建议(a)使用循环并平均时间,(b)针对要测试的每件事使用单独的文件。如果您在一个脚本中有多个计时,则有时它们的顺序可能会有所不同。
DisgruntledGoat

9

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

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 

您输错了:是echo,不是$echo
SuN

9

2020更新

自上次回答这个问题以来已经有很多年了,所以我认为这值得对APM进行更新。

  • AppDynamics已被思科收购,他们曾经提供的永久免费帐户已从其网站中删除。
  • NewRelic已将其价格从149美元/月/主机降低到25美元/月/主机,以与新进入APM市场的竞争对手Datadog竞争,后者提供31美元/月/主机。
  • Datadog APM功能仍然很轻,还有很多不足之处。但是,我认为它们会在明年全年进行改进。
  • Ruxit已被Dynatrace收购。Ruxit由前Dynatrace员工创建,因此这里没有令人震惊的地方。这使Dynatrace可以更好地转换为真正的SaaS模型。如果您愿意,请告别那个笨拙的Java客户端。
  • 现在也有免费/开源选项。签出Apache Skywalking,这在中国的顶级高科技公司中非常流行;PinPoint提供了一个演示,您可以在安装之前进行尝试。这两项都需要您管理主机,因此准备启动一些虚拟机并花一些时间进行安装和配置。
  • 我没有尝试过这些开源APM解决方案中的任何一个,因此我无力推荐它们,但是,我亲自管理了将所有这些APM解决方案部署到内部或云中的多个组织中,以用于数百个应用程序/微服务。因此,我可以自信地说,如果任何一家供应商都符合您的要求,那么您不会出错。


最初于2015年10月回答

这是您问题的直接答案

有没有软件可以衡量?

就在这里。我想知道为什么还没有人提到它。尽管上面建议的答案对于快速检查似乎不错,但从长远来看或对于较大的项目而言,无法扩展。

为什么不使用完全为此而构建的应用程序性能监视(APM)工具呢?查看NewRelic,AppDynamics,Ruxit(均具有免费版本)以监控方法级别的每个应用程序的执行时间,资源使用率和吞吐量。


6

如果要快速测试框架的性能,可以将它放入index.php文件中

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

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

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



4

我想与您分享一个自制函数,该函数用于衡量任何现有函数的速度,最多可包含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"
  }

3

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


3

Zend Studio内置了对使用XDebug或ZendDebugger进行性能分析的支持。它将对您的代码进行概要分析,并确切告诉您每个函数花费了多长时间。这是找出瓶颈所在的绝佳工具。


1

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.