快速从命令行进行基准测试

11

我想对一个PHP脚本进行基准测试,但这同样适用于任何可以从命令行运行的东西。

使用bash,是否有一种简单的方法来基准测试一个脚本,即运行多次命令并计算所需时间?


1
等一下,这个问题在SU上更合适吗?我想我还好。常见的程序员软件工具FAQ。 - rgvcorley
是的,在SU上发布吧。进一步分化我们的社区。 - Petah
1
SU对于这个问题肯定更合适,但是基本上回答这个问题,我认为你可能正在寻找strace - DaveRandom
2
Apache Bench(ab)http://httpd.apache.org/docs/2.0/programs/ab.html - user557846
@rgvcorley 还可以查看LTTng - DaveRandom
使用经典的 times 怎么样? - Jonathon Reinhart
4个回答

16
在命令行中,你可以:
$ time php foobar.php

这里的time是bash内置命令。

对于多次运行:

$ time for a in {1..10}; do php foobar.php; done
real    0m13.042s
user    0m0.021s
sys     0m0.044s

然而,你需要手动计算平均时间。


1
perf stat -r10 php foobar.php 将运行 10 次并为您计算平均值和标准差,至少针对 "task-clock" CPU 时间。(不一定是 wall-clock 时间,如果您在 I/O 上阻塞或同时使用多个核心,则可能会有所不同。) - Peter Cordes

1
如果您只是想对一个PHP脚本进行基准测试,为什么不直接为其编写一个单元测试呢?例如:
<?php

function test() {
    require 'my_script_to_test.php';
}

for ($i = 0; $i < 1000; $i++) {
    $time = microtime(true);
    test();
    $time = microtime(true) - $time;
    echo 'test '.$i.': '.$time;
    // and then you can also average time and w/e 
}

?>

1
因为它没有回答问题的提问者。 - Chris Bloom

0

如果你只是在寻找 PHPBogoMips

$ time php -r 'for($outer=0;$outer<10;++$outer){$t=microtime(true);for($i=0;$i<10000000;++$i){}$t=microtime(true)-$t;$phpBogoMips=10/$t;echo "phpBogoMips: ",$phpBogoMips,PHP_EOL;}'
phpBogoMips: 66.581855298938
phpBogoMips: 74.053284839068
phpBogoMips: 75.23266805498
phpBogoMips: 113.19650341535
phpBogoMips: 84.938811631359
phpBogoMips: 102.55999960876
phpBogoMips: 103.25660631902
phpBogoMips: 84.562239668388
phpBogoMips: 77.247435401588
phpBogoMips: 78.314767444032

real    0m1.307s
user    0m1.124s
sys     0m0.078s
  • 它计算每秒钟 PHP 可以计数到 100 万次。
  • 这里的巨大变化 可能归因于我在笔记本电脑上运行它? 是因为我在笔记本电脑上使用电池运行它。在专用服务器上的截图显示了更一致的结果(最左边是笔记本电脑,它显示):https://i.imgur.com/O8wqojf.png
  • 有人应该再检查一下我的数学,我不确定我做对了。 - 有人已经检查过了!数学似乎没问题。

0

补充谢继雷的回答,如果不想手动计算平均值:

: > benchmark.tmp
for i in {1..10} ; do \
    /usr/bin/time --output benchmark.tmp --append --format "%e" -- custom-cmd-for-benchmark ; \
done
awk '{ total += $1; count++ } END { print total/count }' benchmark.tmp

或者一行代码:

RETRIES=10 ; CMD="custom-cmd-for-benchmark"; /usr/bin/time --output benchmark.tmp --format "%e" -- bash -c "for i in {1..${RETRIES}} ; do ${CMD} ; done" ; awk "{ print \$1/${RETRIES} }" benchmark.tmp

注意:{1..10} 定义了重试次数

注意2:这里没有使用 bash 内置的 time,以便更好地控制输出流(万一 custom-cmd-for-benchmark 输出了什么)!

警告:这将覆盖 benchmark.tmp 文件!

其他想法(为了更好的精度,但会丢失标准输出,这可能会影响基准测试,因为写入 /dev/null 可能比写入终端快):

# This using bash built-in + TIMEFORMAT variable
( export TIMEFORMAT='%3R' ; time for i in {1..10} ; do custom-cmd-for-benchmark >/dev/null ; done ) 2>&1 | awk '{ print $1/10 }'

# This using `date` tool
( date +'%s.%N' | tr -d "\n"; for i in {1..10} ; do custom-cmd-for-benchmark >/dev/null ; done ; date +' %s.%N' ) | awk '{ printf "%.4f",($2 - $1)/10 }'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接