Ruby基准测试不规则性的来源

3

运行此代码:

require 'benchmark'

Benchmark.bm do |x|
  x.report("1+1") {15_000_000.times {1+1}}
  x.report("1+1") {15_000_000.times {1+1}}
  x.report("1+1") {15_000_000.times {1+1}}
  x.report("1+1") {15_000_000.times {1+1}}
  x.report("1+1") {15_000_000.times {1+1}}
end

输出以下结果:

       user     system      total        real
1+1  2.188000   0.000000   2.188000 (  2.250000)
1+1  2.250000   0.000000   2.250000 (  2.265625)
1+1  2.234000   0.000000   2.234000 (  2.250000)
1+1  2.203000   0.000000   2.203000 (  2.250000)
1+1  2.266000   0.000000   2.266000 (  2.281250)

猜测变化是系统环境的结果,但希望确认这是否属实。


1
“猜测变化是系统环境的结果”,你是正确的。 - Guilherme Bernal
@LBg:谢谢,随时可以把那个作为答案发布。 - blunders
2个回答

2

"猜测变化是系统环境的结果",你说得对。

基准测试并不总是精确的。您没有一个完美的常规机器来始终在相同的时间运行某些东西。如果两个基准测试数字太接近,则将它们视为相同,就像在这种情况下一样。


0

我尝试使用eval部分展开循环,虽然它使其更快,但执行时间不够稳定!

$VERBOSE &&= false # You do not want 15 thousand "warning: useless use of + in void context" warnings
# large_number = 15_000_000 # Too large! Caused eval to take too long, so I gave up
somewhat_large_number = 15_000
unrolled = "def do_addition\n" + ("1+1\n" * somewhat_large_number) + "end\n" ; nil
eval(unrolled)

require 'benchmark'

Benchmark.bm do |x|
  x.report("1+1 partially unrolled") { i = 0; while i < 1000; do_addition; i += 1; end}
  x.report("1+1 partially unrolled") { i = 0; while i < 1000; do_addition; i += 1; end}
  x.report("1+1 partially unrolled") { i = 0; while i < 1000; do_addition; i += 1; end}
  x.report("1+1 partially unrolled") { i = 0; while i < 1000; do_addition; i += 1; end}
  x.report("1+1 partially unrolled") { i = 0; while i < 1000; do_addition; i += 1; end}
  x.report("1+1 partially unrolled") { i = 0; while i < 1000; do_addition; i += 1; end}
  x.report("1+1 partially unrolled") { i = 0; while i < 1000; do_addition; i += 1; end}
  x.report("1+1 partially unrolled") { i = 0; while i < 1000; do_addition; i += 1; end}
  x.report("1+1 partially unrolled") { i = 0; while i < 1000; do_addition; i += 1; end}
  x.report("1+1 partially unrolled") { i = 0; while i < 1000; do_addition; i += 1; end}
end

给了我

      user     system      total        real
1+1 partially unrolled  0.750000   0.000000   0.750000 (  0.765586)
1+1 partially unrolled  0.765000   0.000000   0.765000 (  0.765586)
1+1 partially unrolled  0.688000   0.000000   0.688000 (  0.703089)
1+1 partially unrolled  0.797000   0.000000   0.797000 (  0.796834)
1+1 partially unrolled  0.750000   0.000000   0.750000 (  0.749962)
1+1 partially unrolled  0.781000   0.000000   0.781000 (  0.781210)
1+1 partially unrolled  0.719000   0.000000   0.719000 (  0.718713)
1+1 partially unrolled  0.750000   0.000000   0.750000 (  0.749962)
1+1 partially unrolled  0.765000   0.000000   0.765000 (  0.765585)
1+1 partially unrolled  0.781000   0.000000   0.781000 (  0.781210)

为了比较,您在我的计算机上的基准测试得分为:
      user     system      total        real
1+1  2.406000   0.000000   2.406000 (  2.406497)
1+1  2.407000   0.000000   2.407000 (  2.484629)
1+1  2.500000   0.000000   2.500000 (  2.734655)
1+1  2.515000   0.000000   2.515000 (  2.765908)
1+1  2.703000   0.000000   2.703000 (  4.391075)

(实时变化在最后一行,但不包括用户或总计)


@Grimm:我很困惑,你所做的更改似乎比发布的代码更慢。这意味着你的代码太慢了,无法处理15百万次添加“1+1”的操作。我发布的代码与你发布的代码,在稳定性和运行时间方面存在巨大差异。你的代码只是证明了基准测试会更加不稳定。我错过了什么吗?我猜我主要不理解你的回答与我的问题有何关联。感谢你花时间思考这个问题,但我感觉自己错过了你的重点。谢谢! - blunders
@blunders:我无法让“do_addition”包含1500万次加法,所以我改为让它包含15000次加法并调用它1000次。15_000 * 1000 == 15_000_000。 - Andrew Grimm
@Grimm:你的回答是针对什么问题的?我发布的问题基本上是请有人确认基准测试结果只有在运行环境稳定时才能稳定。代码仅作为易于阅读的概念证明提供,并且可以看到结果不稳定。 - blunders

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