背景
以前に sample
と rand
についてベンチマークを比較した記事を書きましたが、いくつか見直すべき点があったため改めて投稿したいと思います。
検証
Kernel.#rand
より Random.rand
前記事では Random.rand
と言いながら Kernel.#rand
(つまり単に rand
) を混同して使っていました。
なので改めて以下のように Kernel.#rand
と Random.rand
を比較してみます。
num = 10000
count = 1000000
Benchmark.bm 20 do |r|
r.report 'Kernel.#rand' do
count.times do
rand(num)
end
end
r.report 'Random.rand' do
count.times do
Random.rand(num)
end
end
end
user system total real
Kernel.#rand 0.190434 0.000193 0.190627 ( 0.190932)
Random.rand 0.084481 0.000194 0.084675 ( 0.084819)
Random.rand
のほうが2倍以上高速でした。
range
より +1
rand
の引数には Range
オブジェクトを受け取ることが出来ますが、1以上10000以下のような範囲なら 1..10000
の Range
より 10000
の Ingeger
を与えて +1
するほうが高速です(rand(10000)
は 0〜9999
の値をランダムで返すため)。
Benchmark.bm 20 do |r|
r.report 'Random.rand(range)' do
num.times do
Random.rand(range)
end
end
r.report 'Random.rand(+1)' do
num.times do
Random.rand(10000) + 1
end
end
end
user system total real
Random.rand(range) 0.243092 0.000319 0.243411 ( 0.244819)
Random.rand(+1) 0.084825 0.000072 0.084897 ( 0.085032)
3倍近く早くなってます。
結果
以上を踏まえて Array#sample
も加えてベンチマークを取ってみます。
num = 10000
range = (1..num)
array = range.to_a
count = 1000000
Benchmark.bm 20 do |r|
r.report 'Array#sample' do
count.times do
array.sample
end
end
r.report 'Kernel.#rand(range)' do
count.times do
rand(range)
end
end
r.report 'Kernel.#rand(+1)' do
count.times do
rand(num) + 1
end
end
r.report 'Random.rand(range)' do
count.times do
Random.rand(range)
end
end
r.report 'Random.rand(+1)' do
count.times do
Random.rand(num) + 1
end
end
end
user system total real
Array#sample 0.143643 0.000186 0.143829 ( 0.144033)
Kernel.#rand(range) 0.137866 0.000146 0.138012 ( 0.138163)
Kernel.#rand(+1) 0.194007 0.000154 0.194161 ( 0.194374)
Random.rand(range) 0.244600 0.000151 0.244751 ( 0.244960)
Random.rand(+1) 0.086753 0.000071 0.086824 ( 0.086926)
結果的には Random.rand
に +1
するのが予想通り最速でしたが、Array#sample
もそこまで遅いわけではないようです。
また、Range
オブジェクトを渡す場合は Random.rand
より Kernel.#rand
のほうが速いというのは意外でした。もし1始まり以外の範囲を使いたい場合は Kernel.#rand
を使っても良さそうです。それと range.to_a
はループの度にやると非常に遅いので事前に用意しておくのが重要です。
最後に
ランチェスターではパフォーマンスにうるさいサーバーサイドエンジニア社員を募集しております!
まずはざっくばらんにお話しさせてください。下記からご応募お待ちしております。
▼https://herp.careers/v1/lanchester/Bucw0mXRKogc
▼https://www.wantedly.com/companies/lanchester
▼採用動画について:https://moovy.jp/job/651