Rubyの文字列の連結速度を測定してGruffで表示してみた
String と StringBuffer の文字列連結速度のテスト - すえひろがりっっっっ!と同様小ネタ。
社会人になって1年たちますが、仕事で「素人かよ!」って思うコードをよく見かけます。
そのトップ10に入るのが「Javaで+= で文字列を連結していてパフォーマンスがすこぶる悪い」コードです。
これをやってた人は、いまだに += で文字列を連結しているコードをよこしてきます。
どうにかならないもんだろうか。
ところで、Ruby でも String の連結は重いのだよね?とふと思ったので += と << で結合した場合の速度を測定してみました。
楽しいRubyによると Ruby でも += で結合するとインスタンスを生成するらしい。
ということは += と << では性能に差が出るはず。
せっかくRubyなのでGruffを試してみます。
バージョン
Mac OS X 10.6.3
CPU 3.06 GHz Intel Core 2 Duo
メモリ 8GB
ruby 1.8.7
gruff 0.3.6
実験コード
require 'rubygems' require 'gruff' require 'benchmark' # 最大結合回数 MAX = 100000 # 刻み STEP = 1000 g = Gruff::Line.new # 指定したやり方で 0 〜 10万回の文字列結合にかかる時間を計測する # 返り値は計測した時間の配列 def bench benchmarks = [] 0.step(MAX, STEP) do |i| benchmarks << Benchmark.measure { str = '' i.times do str = yield str end } end benchmarks.collect{|b| b.real} end g.theme_37signals # += で結合 g.data("+=", bench{|str| str += 'a'}) # concat で結合 g.data("concat", bench{|str| str.concat('a')}) # << で結合 g.data("<<", bench{|str| str << 'a'}) 0.step(MAX, MAX / 4) do |i| g.labels.merge!({i/STEP => i.to_s}) end g.x_axis_label = 'Times' g.y_axis_label = 'seconds' g.write('result.png')
結果
こんな感じ。Gruffで描画するグラフは綺麗だぁ!
横軸が結合の回数、縦軸がかかった時間(秒)です。
"<<"の緑色はほぼ隠れてしまっていますが、"concat"の青色に上書きされていますorz
結論
- たくさん "+=" したいときは、"<<"を使うようにしよう。
- Gruff はグラデーションかかるし綺麗なグラフが簡単に描ける