Ruby1.9で長い文字列を比較的早く作成する方法

UTF-8を使って100MBのクエリーを作成したら激遅だったので,いろいろ調べてみた.

あんまり調べてないけど

UTF-8の文字列を使用せず,バイナリ(ASCII-8BIT)を使用するというのが1番早いんではなかろうかと予想

なので比較してみる

クエリー作成時は範囲での入れ替えをよくやるので範囲オブジェクト使うために2文字にした

比較用コード

#-*- encoding:UTF-8 -*-

times = ARGV[0].to_i
puts times.to_s + "回"

#文字列を+でつなげる
a = ""
b = "aa"

start_time = Time.now
(0...times).each do |i|
  a += b
end
end_time = Time.now
puts "その1:+でつなげる"
puts "全体の時間:"+(end_time - start_time).to_s
puts "1回あたり:"+((end_time - start_time)/times).to_s,""


#文字列を入れ替える(UTF-8で)
a = (" " * times * 2).force_encoding("UTF-8")
b = "aa".force_encoding("UTF-8")

start_time = Time.now
(0...times).each do |i|
  a[(i*2)..(i*2+1)] = b
end
end_time = Time.now
puts "その2:UTF-8で入れ替え"
puts "全体の時間:"+(end_time - start_time).to_s
puts "1回あたり:"+((end_time - start_time)/times).to_s,""


#文字列を入れ替える(バイナリで)
a = (" " * times * 2).force_encoding("ASCII-8BIT")
b = "aa".force_encoding("ASCII-8BIT")

start_time = Time.now
(0...times).each do |i|
  a[(i*2)..(i*2+1)] = b
end
end_time = Time.now
puts "その3:バイナリで入れ替え"
puts "全体の時間:"+(end_time - start_time).to_s
puts "1回あたり:"+((end_time - start_time)/times).to_s,""

結果

1000回
その1:+でつなげる
全体の時間:0.002042
1回あたり:2.042e-06

その2:UTF-8で入れ替え
全体の時間:0.001439
1回あたり:1.439e-06

その3:バイナリで入れ替え
全体の時間:0.001121
1回あたり:1.121e-06
10000回
その1:+でつなげる
全体の時間:0.078724
1回あたり:7.8724e-06

その2:UTF-8で入れ替え
全体の時間:0.039332
1回あたり:3.9332e-06

その3:バイナリで入れ替え
全体の時間:0.01164
1回あたり:1.164e-06
100000回
その1:+でつなげる
全体の時間:10.125697
1回あたり:0.00010125697

その2:UTF-8で入れ替え
全体の時間:2.943017
1回あたり:2.943017e-05

その3:バイナリで入れ替え
全体の時間:0.113457
1回あたり:1.13457e-06

+でつなげたのとUTF-8で入れ替えしたのは1回あたりの時間が順調に伸びた

それに比べて,バイナリでいれかえたのは1回あたりの入れ替えがほぼ変わらない

やっぱりバイナリが最速か・・・

面倒くさいけどRuby1.9.1で巨大な文字列を作成するときは

force_encoding("ASCII-8BIT")

をつけた方がいいみたい