Help us understand the problem. What is going on with this article?

Rubyでベンチマークを取る

More than 3 years have passed since last update.

はじめに

RubyでベンチマークするのはRuby標準のbenchmarkライブラリを使えば簡単にできます。

さらに、より簡単にベンチマークを取れるbenchmark-ipsというGemもあります。
このGemは、RailsにContributionする際にベンチマークを取る方法として、公式に指定されてもいます。

http://railsguides.jp/contributing_to_ruby_on_rails.html#ベンチマークを行う

以下ではこの2つの使い方を簡単に見ていきます。

benchmark-ips

概要

ipsとは"iterations per second"の略になります。

このGemでベンチマークすると「処理回数(イテレーション回数)/秒」を計測してくれます。
次の項で説明するRuby標準のbenchmarkライブラリは自分で実行回数を指定しなければならないのですが、こちらはその手間がなく、かつ処理ごとに何倍の速度差があるかを出してくれるので便利です。

使い方

まずはインストールしましょう

console
$ gem i benchmark-ips

コードの書き方は以下のとおり。(公式から引用・整形)

計測コード
require 'benchmark/ips'

Benchmark.ips do |x|
  x.report("addition") { 1 + 2 }
  x.report("addition2") do |times|
    i = 0
    while i < times
      1 + 2
      i += 1
    end
  end
  x.report("addition3", "1 + 2")
  x.report("addition-test-long-label") { 1 + 2 }

  x.compare!
end

実行結果は以下のようになります

結果
Calculating -------------------------------------
            addition    71.254k i/100ms
           addition2    68.658k i/100ms
           addition3    83.079k i/100ms
addition-test-long-label
                        70.129k i/100ms
-------------------------------------------------
            addition     4.955M (± 8.7%) i/s -     24.155M
           addition2    24.011M (± 9.5%) i/s -    114.246M
           addition3    23.958M (±10.1%) i/s -    115.064M
addition-test-long-label
                         5.014M (± 9.1%) i/s -     24.545M

Comparison:
           addition2: 24011974.8 i/s
           addition3: 23958619.8 i/s - 1.00x slower
addition-test-long-label:  5014756.0 i/s - 4.79x slower
            addition:  4955278.9 i/s - 4.85x slower

reportメソッドにテストの名前(必須ではない)と計測したい処理を渡します。
compare!は必須ではないですが、書いておくと結果に"Comparison"という項目が出来て、
一目で最速の処理や遅い処理は何倍遅いかを表示してくれるので便利です。

設定

細かい挙動は正直よくわかってないのですが、実行時に2つ指定できる設定があります。
timeは計測する時間、warmupはおそらく処理のオーバーヘッドを少なくするために前処理(ウォーミングアップ)の時間を与えるものだと思います。多分

指定方法は以下の2通りのどちらかでやればOK

Benchmark.ips do |x|

  x.config(
    time: 8, # default 5
    warmup: 3 # default 2
  )

  # or

  x.time = 5
  x.warmup = 2

  ## 後略 ##
end

GC

ベンチマークをしている時だけGCを無効にしたい場合も多々あると思いますが、その時は以下のリンク先のコードをコピペしてやれば大体OK

https://github.com/evanphx/benchmark-ips#custom-suite

Benchmark

Ruby標準ベンチマークライブラリの使い方は以下のとおり

ipsとの違いはイテレーション回数を指定しなければいけないことと、Benchmark.bmを呼び出すことでしょうか。
基本的にはipsの方が便利なので、そっち使いましょう。

計測コード
require 'benchmark'

n = 10000000
Benchmark.bm(7) do |x| # 引数の7は結果の表示を揃えるためで必須ではないです
  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
結果
              user     system      total        real
for:      1.100000   0.010000   1.110000 (  1.098665)
times:    1.080000   0.000000   1.080000 (  1.085871)
upto:     1.070000   0.000000   1.070000 (  1.065394)
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away