如何衡量脚本的平均执行时间?


23

我有两个脚本,每个脚本都计算一个数字的阶乘。我想知道哪个更快。该time命令以毫秒为单位,结果有时会不同:

piousbox@piousbox-laptop:~/projects/trash$ time ruby fac2.rb
30414093201713378043612608166064768844377641568960512000000000000

real    0m0.089s
user    0m0.052s
sys 0m0.028s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac1.rb
30414093201713378043612608166064768844377641568960512000000000000

real    0m0.091s
user    0m0.048s
sys 0m0.036s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac1.rb
30414093201713378043612608166064768844377641568960512000000000000

real    0m0.088s
user    0m0.048s
sys 0m0.040s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac2.rb
30414093201713378043612608166064768844377641568960512000000000000

real    0m0.088s
user    0m0.048s
sys 0m0.028s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac1.rb
30414093201713378043612608166064768844377641568960512000000000000

real    0m0.087s
user    0m0.064s
sys 0m0.028s
piousbox@piousbox-laptop:~/projects/trash$ time ruby fac2.rb
30414093201713378043612608166064768844377641568960512000000000000

real    0m0.089s
user    0m0.068s
sys 0m0.016s
piousbox@piousbox-laptop:~/projects/trash$ 

我该如何计算运行脚本的平均时间?我可以解析并平均100的输出,time但是我想有更好的解决方案?


Answers:


4

不,您的平均想法是正确的。

脚本执行取决于很多因素,但是,它需要在设置时间(将解释器加载到内存中,设置,并可能将代码编译为字节码或机器代码)与实际执行时间之间进行分配。

为了更好地关注内部执行时间,您可以在脚本本身中执行循环(即,不计算一个阶乘,而是在一次脚本执行中计算100次。脚本将被设置一次,内部例程将执行100次次)。

为了专注于总时间,您可以执行脚本一百次并取平均结果。理想情况下,应该将那些执行分开,以使系统每次都以“参考状态”(或与脚本无关的状态)返回。例如,解释器本身将被缓存在内存中,因此脚本的第一次执行将比随后的执行慢很多。

为了更好地了解算法,我认为最好的方法是这样的(在其他闲置的机器上):

  • 将算法包装在一个函数中。
  • 在控制应用程序中:
    • 调用一次函数
    • 获取系统(“挂钟”)时间并增加10(或合理的N)秒
    • 进入循环并开始计算迭代次数
    • 每次调用该函数后,增加计数器
    • 如果系统时间低于保存的时间,请执行另一个循环
    • 从当前挂钟时间获得确切的N,可能是浮点数
    • 显示计数器除以N:即迭代次数/秒。

该应用程序仅运行一次,所有设置和启动均由第一个无定时的迭代完成,因此这应将开销降至最低(可能需要时间调用除外)。

如果函数接收到输入,则最好使用以固定值作为种子的PRNG为输入提供随机的输入序列,以确保要测试的函数的两个版本均接收相同的值。这避免了一个函数由于“幸运数字”而表现得明显更好的功能(例如,我记得Hillsort算法的一种变体,如果要排序的项目数的形式为2 k -1且k s 较小,则其表现明显更好)。


对,谢谢 我注意到随后的通话越来越短。我现在在脚本内部运行循环,发现一种算法肯定比另一种算法快。
Victor Piousbox 2013年

39

您可以循环运行程序的迭代。将总时间除以迭代次数:

time for i in {1..10}; do sleep 1; done
real    0m10.052s
user    0m0.005s
sys 0m0.018s

2
超级简单,喜欢它。我也从未见过{1..10},并且对它的工作感到困惑,无法在bash手册中找到它。唯一可悲的是,您不知道结果的传播范围(最小和最大时间)。
w00t 2014年

@ w00t:man -P 'less +/Brace\ Expansion' bash
user2683246'9

谢谢@ user2683246!然后,我还在gnu.org/software/bash/manual/bash.html#Brace-Expansion中找到了它-少用btw很好用。现在,我也很好奇何时出现这种情况……
w00t 2015年

1
啊哈,版本3,距离
w00t

2
如果此方法不适用于即将到来的Google员工,则可能是因为您没有参加bash/bin/bash在此之前尝试运行。
科里·克莱恩

14

有一个名为multitime的工具可以做到这一点:多次运行一条命令,测量花费的时间(实际/用户/系统的平均时间,最小/最大和中值时间会自动计算)

例如,要测量一个相似的脚本100次:

multitime -q -n 100 "fact1.sh"
===> multitime results
1: -q fact1.sh
            Mean        Std.Dev.    Min         Median      Max
real        0.122       0.032       0.086       0.116       0.171       
user        0.148       0.044       0.096       0.137       0.223       
sys         0.023       0.019       0.000       0.014       0.061 

12

这很旧,但是当我在寻找以前使用过但找不到的命令时,它在Google上的排名很高。无论如何,我首选的方式是:

perf stat -r 10 -B sleep 1

这给出了很多细节,包括最后的平均执行时间:

1.002248382 seconds time elapsed                   ( +-  0.01% )


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.