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

Posted

技术标签:

【中文标题】如何测量用 PHP 编写的代码的速度? [关闭]【英文标题】:How can I measure the speed of code written in PHP? [closed] 【发布时间】:2009-07-29 13:20:45 【问题描述】:

我怎么能说哪一类(都做同样的工作)执行得更快?有软件可以测量吗?

【问题讨论】:

在linux中使用time命令 【参考方案1】:

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

相当“幼稚”的方法是在一段代码之前和之后使用 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_PROFILE 的参数作为 GET 数据的可能性,仅为我需要的页面激活分析。 我的 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...)

这使您可以很好地了解应用程序中需要花费的时间 - 有时它肯定有助于定位 使一切变慢的函数^^

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

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

【讨论】:

QCacheGrind 的 Windows 版本存在 :-) sourceforge.net/projects/qcachegrindwin【参考方案2】:

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

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

您也可以使用像 http://xdebug.org/ 这样的分析器。

【讨论】:

为了提高准确性,我建议 (a) 使用循环并平均时间和 (b) 为您正在测试的每件事使用单独的文件。如果您在一个脚本中有多个时间点,它们的顺序有时会有所不同。【参考方案3】:

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

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【参考方案4】:

2020 年更新

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

AppDynamics 已被 Cisco 收购,他们曾经提供的永久免费帐户已从其网站上移除。 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(都有免费版本)来监控每个应用程序的执行时间、资源使用情况、吞吐量到方法级别。

【讨论】:

【参考方案5】:

如果你想快速测试一个框架的性能,你可以放入index.php文件

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

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

每次您将获得以 毫秒 为单位的执行时间。因为微秒在测试框架案例时并没有太大用处。

【讨论】:

这非常简单而且效果很好。谢谢!【参考方案6】:

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

【讨论】:

【参考方案7】:

我想与你分享一个自制函数,我用它来测量任何现有函数的速度,最多 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"
  

【讨论】:

【参考方案8】:

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

【讨论】:

【参考方案9】:

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

【讨论】:

【参考方案10】:

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

【讨论】:

以上是关于如何测量用 PHP 编写的代码的速度? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

为啥使用 PHP 和 cURL 测量我的 socks5 速度不起作用?

用 C++ 编写 PHP 扩展 [关闭]

如何测量数据结构的内存使用情况? [复制]

如何将代码从 C# 转换为 PHP [关闭]

如何保护网站代码 PHP/JS? [关闭]

PHP程序写得越多发现响应速度越慢,请问写程序中应该注意些啥?我是新手!怎么提高程序响应时间!