耗时统计——benchmark

作者:周星 发布:2017-10-07

       在做一些功能时,我们经常要考虑到性能,其中一个非常重要的指标就是耗时,页面刷新半天打不开,或者执行一段代码用了很长时间,但是不确定卡在了那里,之前我会自作聪明,在 console 里这样做:

def a
  start_time = Time.now
  # 执行那段代码
  puts Time.now - start_time
end

       嗯,自以为好像很牛X的样子,但是实际上却是:弱爆了!因为 ruby 有一个模块 benchmark,它提供了非常强大的计算耗时的功能,下面我们就来详细看一下 benchmark 的用法吧。

我们先看一个简单的例子,计算 "a" * 10_000_000的耗时:

#!/usr/bin/ruby
require 'benchmark'

puts Benchmark.measure { "a" * 10_000_000 }

执行的结果是:

  0.010000   0.000000   0.010000 (  0.003167)

       根据每个人机器的性能等原因,执行的结果可能会有些差距。结果给了我们 4 个数字,它们分别是:用户 CPU 时间、系统 CPU 时间 、用户 CPU 和 系统 CPU总和、实际耗时,单位都是秒,报告显示给我们,执行 "a" * 10_000_000耗时 0.01 秒。

通过bm方法,我们还可以让我们很直观的查看性能对比,

#!/usr/bin/ruby
require 'benchmark'

n = 50000
Benchmark.bm do |x|
  x.report { for i in 1..n; a = "1"; end }
  x.report { n.times do   ; a = "1"; end }
  x.report { 1.upto(n) do ; a = "1"; end }
end

我机器上的执行结果为:

user       system     total       real
0.010000   0.000000   0.010000 (  0.006517)
0.000000   0.000000   0.000000 (  0.005543)
0.010000   0.000000   0.010000 (  0.005777)

为了方便查看,我们还可以为每个 report 设一个 label

#!/usr/bin/ruby
require 'benchmark'

n = 50000
Benchmark.bm(7) do |x|
  x.report("for:")   { for i in 1..n; a = "1"; end }
  x.report("times:") { n.times do   ; a = "1"; end }
  x.report("upto:")  { 1.upto(n) do ; a = "1"; end }
end

bm 方法的参数为7表示 label 和结果之间的 宽度,也是为了方便我们查看的,结果如下:

             user     system       total       real
for:      0.010000   0.000000   0.010000 (  0.008925)
times:    0.010000   0.000000   0.010000 (  0.010999)
upto:     0.000000   0.000000   0.000000 (  0.006336)

       benchmark 计算的耗时,有些时候是依赖代码的执行顺序的,假如第一个 report 执行的代码耗用了大量的内存或者没有一个好的回收机制,下面代码的执行时间自然会受此影响,benchmark 提供了一个 bmbm 方法来避免这个问题,下面的例子对比浮点数数组不同排序方法的耗时:

require 'benchmark'

array = (1..1000000).map { rand }

Benchmark.bmbm do |x|
  x.report("sort!") { array.dup.sort! }
  x.report("sort")  { array.dup.sort  }
end

程序会逐行的输出:

Rehearsal -----------------------------------------
sort!   1.450000   0.010000   1.460000 (  1.451287)
sort    1.370000   0.000000   1.370000 (  1.377477)
-------------------------------- total: 2.830000sec

            user     system      total        real
sort!   1.350000   0.000000   1.350000 (  1.345067)
sort    1.330000   0.000000   1.330000 (  1.326089)

通过 benchmark 方法,我们可以更好的格式化输出的信息

require 'benchmark'
include Benchmark         # we need the CAPTION and FORMAT constants

n = 50000
Benchmark.benchmark(CAPTION, 7, FORMAT, ">total:", ">avg:") do |x|
  tf = x.report("for:")   { for i in 1..n; a = "1"; end }
  tt = x.report("times:") { n.times do   ; a = "1"; end }
  tu = x.report("upto:")  { 1.upto(n) do ; a = "1"; end }
  [tf+tt+tu, (tf+tt+tu)/3]
end

支付宝扫码赞助博主


评论(0)