=~ と scan のパフォーマンスについて
以前も調べたのだけど、ちゃんとしたロジックで再検証してみる
以前、scan と正規表現のグループ化 - @sugamasao.blog.title # => ”コードで世界を変えたい” でも調べていて、scan の方が遅い事がわかったのだけど、もうちょっとまともなロジックで再検討してみる。
下記は MIME エンコード*1された文字列から文字コードとエンコード方式と、大本の文字列を抜き出す正規表現。
それらを 10000 回繰り返してベンチマークを取ってみた。
ソースはこちら
1 require 'benchmark' 2 3 n = 10000 4 5 def reg_test(str) 6 if str =~ /.*?=\?(.+?)\?(.)\?(.+?)\?=/ 7 #puts $1 8 #puts $2 9 #puts $3 10 end 11 end 12 13 def scan_test(str) 14 str.scan( /.*?=\?(.+?)\?(.)\?(.+?)\?=/) do |s| 15 #puts s[0] 16 #puts s[1] 17 #puts s[2] 18 end 19 end 20 21 Benchmark.bm do |b| 22 b.report("reg_test") { n.times { reg_test("=?UTF-8?B?44GC44GC44GC44GC44GC44GC?=") } } 23 b.report("scan_test") { n.times { scan_test("=?UTF-8?B?44GC44GC44GC44GC44GC44GC?=") } } 24 end
ちなみに、コメントアウトしてある部分を外すと、以下のように出力される。
一番上から、文字コード、エンコード方式(今回は BASE64)、エンコードされた文字列の順。
UTF-8
B
44GC44GC44GC44GC44GC44GC
測定結果
:! ruby test.rb user system total real reg_test 0.050000 0.000000 0.050000 ( 0.052958) scan_test 0.070000 0.000000 0.070000 ( 0.070909)
結論
やっぱり scan の方が時間掛かる。この手のパース処理って他に高速化できる手段はあるのだろうか。やっぱ racc 使えって感じ?
*1:日本語のメール件名に使われたりするヤツね