sort.reverseとsort_by{ |val| -val }の速度差 2

前回のだと、sortは正数の比較でsort_by{-val}は負数の比較なのでもしかしたらそれで何かあるのかなと思い、より条件を公平にするために初期値を-5.0〜5.0までの0.1刻みにしてみることにした。

require "benchmark"

array = Array.new(101){ |index| (index-50)/10.0 }.sort_by{ rand }

array1 = array.dup
array2 = array.dup
array3 = array.dup

Benchmark.bm(16) do |bm|
  bm.report("sort.reverse    "){ 1000.times{ array1.sort.reverse                      } }
  bm.report("sort_by{-val}   "){ 1000.times{ array2.sort_by{ |value| -value }         } }
  bm.report("sort_by.reverse "){ 1000.times{ array3.sort_by{ |value|  value }.reverse } }
end

結果

                      user     system      total        real
sort.reverse      0.040000   0.140000   0.180000 (  0.176166)
sort_by{-val}     0.450000   0.170000   0.620000 (  0.621983)
sort_by.reverse   0.350000   0.260000   0.610000 (  0.607328)
                      user     system      total        real
sort.reverse      0.030000   0.150000   0.180000 (  0.179240)
sort_by{-val}     0.420000   0.230000   0.650000 (  0.645518)
sort_by.reverse   0.460000   0.110000   0.570000 (  0.568760)
                      user     system      total        real
sort.reverse      0.010000   0.180000   0.190000 (  0.180895)
sort_by{-val}     0.480000   0.180000   0.660000 (  0.665484)
sort_by.reverse   0.450000   0.140000   0.590000 (  0.588774)

やっぱり順番は同じ。

件数が1件しか増えてないのに、sort.reverseが3倍くらい時間かかってる。初期値をIntegerとFloatのみにして追試してみたら、どうやらFloatの比較が遅いらしい。
sort_byは遅いけど速度が安定してる。でも計算結果をマイナスするくらいならそのままにしてreverseした方が早い。ずっとマイナスした方が早いのかと思ってたけど、今後は意味的にもわかりやすくなるのでsort_by.reverseを使うことにしよう。