4

我正在尝试确定我的 PHP 脚本的 CPU 使用率。我刚刚发现这篇文章详细介绍了如何查找系统和用户 CPU 使用时间(第 4 节)。

但是,当我尝试这些示例时,我得到了完全不同的结果。

一个例子

sleep(3);

$data = getrusage();
echo "User time: ".
    ($data['ru_utime.tv_sec'] +
    $data['ru_utime.tv_usec'] / 1000000);
echo "System time: ".
    ($data['ru_stime.tv_sec'] +
    $data['ru_stime.tv_usec'] / 1000000);

结果是:

User time: 29.53
System time: 2.71

示例 2

for($i=0;$i<10000000;$i++) {

}

// Same echo statements

结果:

User time: 16.69
System time: 2.1

示例 3

$start = microtime(true);  
while(microtime(true) - $start < 3) {  

}  

// Same echo statements

结果:

User time: 34.94
System time: 3.14

显然,除了第三个示例中的系统时间之外,没有任何信息是正确的。那么我做错了什么?我真的很想能够使用这些信息,但它必须是可靠的。

我正在使用 Ubuntu Server 8.04 LTS(32 位),这是以下输出php -v

PHP 5.2.4-2ubuntu5.10 with Suhosin-Patch 0.9.6.2 (cli) (built: Jan  6 2010 22:01:14)
Copyright (c) 1997-2007 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2007 Zend Technologies
4

2 回答 2

3

您可以使用系统“时间”命令在外部验证此信息:

/usr/bin/time php script.php

这将打印如下内容:

0.03user 0.00system 0:03.04elapsed 0%CPU (0avgtext+0avgdata 32752maxresident)k
0inputs+0outputs (0major+2234minor)pagefaults 0swaps

当然,不要忘记 getrusage() 信息是使用的 CPU 时间,而 microtime() 是挂钟时间。程序可能会根据墙上的时钟运行 10 分钟,但内部可能只使用几秒钟的 CPU 时间。然后是系统上运行的所有后台程序争夺 CPU 时间、资源争用以及定期的内务管理。

涉及的因素太多,无法在如此短的时间内获得准确的时间。执行while(microtime())循环版本的三个运行,我得到以下时间:

用户:0.98、0.09、0.90 系统:0.12、0.05、0.94

显然差异很大。即使只是一个简单<? print_r(getrusage()) ?>的 utime/stimes 范围从 0 到 0.03。

尝试运行更长时间的循环,并在其中做一些事情以增加 CPU 使用率。现在,您的数字太小而无法准确测量。

于 2010-04-28T18:53:35.100 回答
0

多亏了Marc B 的建议,我才能够弄清楚,荒谬的短时间导致了getrusage()的计算错误。

我创建了一个解决方法来丢弃这些不准确的数字。这是代码:

define('SCRIPT_START', microtime(1));

register_shutdown_function('record_activity');

/* Do work here */

function record_activity()
{
    $data = getrusage();
    $cpuu = ($data['ru_utime.tv_sec'] + $data['ru_utime.tv_usec'] / 1000000);
    $cpus = ($data['ru_stime.tv_sec'] + $data['ru_stime.tv_usec'] / 1000000);
    $renderedtime = round(microtime(1) - SCRIPT_START, 6);

    // Have some log function to put this info somewhere
    insert_record($renderedtime,
        //Only pass user CPU time if it's less than or equal to rendered time
        ($renderedtime >= $cpuu ? $cpuu : NULL ),
        //Only pass system CPU time if it's less than or equal to rendered time
        ($renderedtime >= $cpus ? $cpus : NULL ));
}

希望这对遇到相同问题的其他人有所帮助。

于 2010-04-28T19:53:54.317 回答