Ruby1.9ではBignumのインクリメントはFixnumのインクリメントに比べて倍ぐらい遅い
タイトルで完結シリーズ。しかも割と「いまさら」ではありますが。
システムの稼働中に延々とインクリメントする変数が必要だったので、実際に実験してみた。
先に結果を。
***** Hello, this is a test benchmark script for Incrementing Integer number. Is Fixnum faster than Bignum? ***** your Ruby version is: 1.9.2 your Ruby's Max value of Fixnum is: 4611686018427387903 [ 4611686018427387903.class => Fixnum ] [ 4611686018427387904.class => Bignum ] * Fixnum test range: [0(Fixnum) - 1000000(Fixnum)] 50times trial. -> 4.994632071 sec. (50times) 0.09989264142 sec/trial. 9.989264141999999e-08 sec/increment. * Intermediate test range: [4611686018426887903(Fixnum) - 4611686018427887903(Bignum)] 50times trial. -> 8.038869072 sec. (50times) 0.16077738144 sec/trial. 1.6077738144000002e-07 sec/increment. * Bignum test range: [4611686018427387904(Bignum) - 4611686018428387904(Bignum)] 50times trial. -> 11.139960695 sec. (50times) 0.2227992139 sec/trial. 2.227992139e-07 sec/increment.
FixnumとBignumの変数を100万回インクリメントする処理を50回やった平均。
Fixnumのテストでは[0〜1,000,000]まで、Bignumのテストでは[Fixnum_MAX+1 〜 Fixnum_MAX+1+1,000,000]まで。
また、Fixnum_MAXをまたぐ形(Intermediate)でも100万回のインクリメントを計測してみた。
FixnumとBignumの差が約6.2秒に対して、FixnumとIntermediate、IntermediateとBignumの差が約3.1秒なので、まあ妥当なところでしょう。
実験に使ったソースはこちら:
#!/bin/env ruby def _bench bef = Time.now yield diff = Time.now - bef return diff end def bench_it(from, num_add, times) return _bench do times.times { num = from num_add.times { num += 1 } } end end # from http://ja.w3support.net/index.php?db=so&id=535721 FIXNUM_MAX = (2**(0.size * 8 -2) -1) puts "***** Hello, this is a test benchmark script for" puts " Incrementing Integer number. Is Fixnum faster than Bignum? *****" puts puts " your Ruby version is: #{RUBY_VERSION}" puts " your Ruby's Max value of Fixnum is: #{FIXNUM_MAX}" puts " [ #{FIXNUM_MAX}.class => #{(FIXNUM_MAX).class} ]" puts " [ #{FIXNUM_MAX+1}.class => #{(FIXNUM_MAX+1).class} ]" puts num_add = 1_000_000 times = 50 from = 0 puts "* Fixnum test" puts " range: [#{from}(#{from.class}) - #{from+num_add}(#{(from+num_add).class})] #{times}times trial." elapsed_time = bench_it(from, num_add, times) puts " -> #{elapsed_time} sec. (#{times}times)" puts " #{elapsed_time / times} sec/trial." puts " #{elapsed_time / times / num_add} sec/increment." puts from = FIXNUM_MAX - (num_add / 2) puts "* Intermediate test" puts " range: [#{from}(#{from.class}) - #{from+num_add}(#{(from+num_add).class})] #{times}times trial." elapsed_time = bench_it(from, num_add, times) puts " -> #{elapsed_time} sec. (#{times}times)" puts " #{elapsed_time / times} sec/trial." puts " #{elapsed_time / times / num_add} sec/increment." puts from = FIXNUM_MAX + 1 puts "* Bignum test" puts " range: [#{from}(#{from.class}) - #{from+num_add}(#{(from+num_add).class})] #{times}times trial." elapsed_time = bench_it(from, num_add, times) puts " -> #{elapsed_time} sec. (#{times}times)" puts " #{elapsed_time / times} sec/trial." puts " #{elapsed_time / times / num_add} sec/increment."