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

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

我有两个脚本,每个脚本都计算一个数字的阶乘。我想知道哪个更快。命令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但我想有更好的解决方案?

答案1

不,你关于平均的想法是正确的。

脚本执行取决于很多因素,但它要分为设置时间(在内存中加载解释器、设置以及可能将代码编译为字节码或机器码)和真实执行时间。

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

为了关注总时间,您需要执行脚本一百次并取平均值。理想情况下,您应该将这些执行分开足够远,以便系统每次都返回“参考状态”(或与脚本无关的状态)。例如,解释器本身将被缓存在内存中,以便最先脚本的执行将明显比后续脚本慢。

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

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

该应用程序仅运行一次,所有设置和启动都由第一次不计时迭代完成,因此这应该可以最大限度地减少开销(可能除了时间调用)。

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

答案2

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

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

答案3

有一个工具叫多时间它的作用是:多次运行命令,测量其花费的时间(实际/用户/系统,自动计算平均值、最小值/最大值和中值时间)

例如,测量类似脚本 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 

答案4

超精细是另一种选择。

使用示例:

hyperfine --warmup 3 'ruby fac1.rb'

相关内容