【Ruby】 FizzBuzz問題各繰り返しによる処理速度の計測

# はじめに

今回は7つの繰り返し条件式(for, while, each, until, times, upto, downto)を使ってそれぞれ検証します。
[gem benchmark_driver](https://github.com/benchmark-driver/benchmark-driver)を使います。


@scivola さん、アドバイスありがとうございます。


# 共通条件

- 繰り返し上限値：10000
- 前判定
- FizzBuzz条件式は全て同じ


# 実行コード

```ruby:benchmark.rb
require 'benchmark_driver'

Benchmark.driver do |x|

  n = 10000
  
  x.report  "#{n}回 for", %{ 
    for i in 1..#{n} do
      if i % 15 == 0
           "FizzBuzz"
      elsif i % 3 == 0
           "Fizz"
      elsif i % 5 == 0
           "Buzz"
      else
           i
      end
    end
  }

  x.report  "#{n}回 while", %{
    i = 1
    while i <= #{n} do
      if i % 15 == 0
           "FizzBuzz"
      elsif i % 3 == 0
           "Fizz"
      elsif i % 5 == 0
           "Buzz"
      else
           i
      end
    i += 1
    end
  }

  x.report  "#{n}回 each", %{
    (1..#{n}).each { |i| 
      if i % 15 == 0
           "FizzBuzz"
      elsif i % 3 == 0
           "Fizz"
      elsif i % 5 == 0
           "Buzz"
      else
           i
      end
    }
  }

  x.report  "#{n}回 until", %{
    i = 0
    until i >= #{n}
      if i % 15 == 0
           "FizzBuzz"
      elsif i % 3 == 0
           "Fizz"
      elsif i % 5 == 0
           "Buzz"
      else
           i
      end
    i += 1
    end
  }

  x.report  "#{n}回 times", %{
    #{n}.times do |i| 
      if i % 15 == 0
           "FizzBuzz"
      elsif i % 3 == 0
           "Fizz"
      elsif i % 5 == 0
           "Buzz"
      else
           i
      end
    end
  }

  x.report  "#{n}回 upto", %{
    1.upto(#{n}) do |i| 
      if i % 15 == 0
           "FizzBuzz"
      elsif i % 3 == 0
           "Fizz"
      elsif i % 5 == 0
           "Buzz"
      else
           i
      end
    end
  }

  x.report  "#{n}回 downto", %{
    #{n}.downto(1) do |i| 
      if i % 15 == 0
           "FizzBuzz"
      elsif i % 3 == 0
           "Fizz"
      elsif i % 5 == 0
           "Buzz"
      else
           i
      end
    end
  }
end
```

# 結果

一番早かったのがwhileでしたがuntilとどんぐりの背比べ程度の差でした。


```text

Warming up --------------------------------------
          10000回 for    819.214 i/s -     860.000 times in 1.049787s (1.22ms/i)
        10000回 while     1.453k i/s -      1.460k times in 1.004510s (688.02μs/i)
         10000回 each    946.035 i/s -      1.001k times in 1.058100s (1.06ms/i)
        10000回 until     1.386k i/s -      1.480k times in 1.067445s (721.25μs/i)
        10000回 times    918.016 i/s -     920.000 times in 1.002161s (1.09ms/i)
         10000回 upto    867.162 i/s -     920.000 times in 1.060932s (1.15ms/i)
       10000回 downto    854.204 i/s -     890.000 times in 1.041906s (1.17ms/i)
Calculating -------------------------------------
          10000回 for    855.651 i/s -      2.457k times in 2.871499s (1.17ms/i)
        10000回 while     1.424k i/s -      4.360k times in 3.061448s (702.17μs/i)
         10000回 each    869.559 i/s -      2.838k times in 3.263725s (1.15ms/i)
        10000回 until     1.393k i/s -      4.159k times in 2.985758s (717.90μs/i)
        10000回 times    862.132 i/s -      2.754k times in 3.194408s (1.16ms/i)
         10000回 upto    845.573 i/s -      2.601k times in 3.076020s (1.18ms/i)
       10000回 downto    858.080 i/s -      2.562k times in 2.985737s (1.17ms/i)

Comparison:
        10000回 while:      1424.2 i/s 
        10000回 until:      1392.9 i/s - 1.02x  slower
         10000回 each:       869.6 i/s - 1.64x  slower
        10000回 times:       862.1 i/s - 1.65x  slower
       10000回 downto:       858.1 i/s - 1.66x  slower
          10000回 for:       855.7 i/s - 1.66x  slower
         10000回 upto:       845.6 i/s - 1.68x  slower
```

# 参考文献

- [[Ruby]benchmarkで処理速度を計測](http://www.cl9.info/entry/2018/01/08/000000)

- [Ruby でベンチマークを取る方法](https://qiita.com/scivola/items/c5b2aeaf7d67a9ef310a)