こんにちは、いつもお世話になっております。
今、コンパイラを学ぶにあたり、RubyによるC言語の字句解析器を試しに作成しているのですが、そのコードの中で、標準入力から取得した文字列が、C言語の予約語(if,return等)に当てはまるか否かのチェックを、ハッシュで行うようにしました。
その理由としては、配列の場合だと、==演算を最大で配列のサイズ分行うことになってしまい、実行速度が遅くなると思ったので、取得した文字列をハッシュ演算にかけることで、要素のアドレスを直で得ることができるハッシュを使うことにしました。(ハッシュの理解が間違っていたら申し訳ございません。)
今回質問させていただきたいことは、ハッシュのキーと要素のクラスを文字列とシンボルで入れ替えた場合、実行速度はどうなるかということです。
調べたところ、ハッシュではシンボルを利用したほうが実行速度が速いと一般的に言われていますが、では、ハッシュの中のキーと要素のどちらにシンボルを利用したほうが速いのだろうかと思った次第です。(なお、調べた例では、キーにシンボルを利用していることが多かった。)
以下試しに書いたコードです。
ex7alt.rbはキーがシンボル、値が文字列です。
ex7alt2.rbはキーが文字列、値がシンボルです。
また、一応呼び出しにかかる時間も計測してみました。
ex7alt.rb
Ruby
1# coding: utf-8 2require 'benchmark' 3reserved_words={auto:"auto", break:"break", case:"case", char:"char", const:"const", continue:"continue", default:"default", double:"double", do:"do", else:"else", enum:"enum", extern:"extern", float:"float", for:"for", goto:"goto", if:"if", int:"int", long:"long", register:"register", return:"return", short:"short", signed:"signed", sizeof:"sizeof", static:"static", struct:"struct", switch:"switch", typedef:"typedef", union:"union", unsigned:"unsigned", void:"void", volatile:"volatile", while:"while"} 4 5print "input a line: " 6while line=gets do 7 until line.empty? do 8 case line 9 when /\A\s+/ 10 when /\A([0-9]+)/ 11 puts "number (#{$1})" 12 when /\A([_a-zA-Z]\w*)/ 13 word = $1.to_sym 14 result = Benchmark.realtime do 15 if reserved_words[word] 16 puts "reserved words (#{$1})" 17 else 18 puts "identifier (#{$1})" 19 end 20 end 21 puts "所要時間 #{result}s" 22 when /\A(\S)/ 23 puts "other (#{$1})" 24 end 25 line = $'.to_s 26 end 27end
ex7alt2.rb
Ruby
1# coding: utf-8 2require 'benchmark' 3reserved_words={"auto"=>:auto, "break"=>:break, "case"=>:case, "char"=>:char, "const"=>:const, "continue"=>:continue, "default"=>:default, "double"=>:double, "do"=>:do, "else"=>:else, "enum"=>:enum, "extern"=>:extern, "float"=>:float, "for"=>:for, "goto"=>:goto, "if"=>:if, "int"=>:int, "long"=>:long, "register"=>:register, "return"=>:return, "short"=>:short, "signed"=>:signed, "sizeof"=>:sizeof, "static"=>:static, "struct"=>:struct, "switch"=>:switch, "typedef"=>:typedef, "union"=>:union, "unsigned"=>:unsigned, "void"=>:void, "volatile"=>:volatile, "while"=>:while} 4 5print "input a line=> " 6while line=gets do 7 until line.empty? do 8 case line 9 when /\A\s+/ 10 when /\A([0-9]+)/ 11 puts "number (#{$1})" 12 when /\A([_a-zA-Z]\w*)/ 13 result = Benchmark.realtime do 14 if reserved_words[$1] 15 puts "reserved words (#{$1})" 16 else 17 puts "identifier (#{$1})" 18 end 19 end 20 puts "所要時間 #{result}s" 21 when /\A(\S)/ 22 puts "other (#{$1})" 23 end 24 line = $'.to_s 25 end 26end
入力には下のテキストファイルを使用しました。
sample.txt
text
1return 2if 3double 4int 5unsigned 6while
実行して見たところ、余り大差はないように見えますが、すこしだけ、シンボルをキーとしたときのほうが速いように見えます。しかし、どうしてこのような結果となるのかがわかりません。
もし、このような実行結果となる要因や、ハッシュのキーと要素のクラスを文字列とシンボルで入れ替えた場合、実行速度はどうなるかということについて、ご存じの方がいらっしゃいましたら教えていただけたら幸いです。

回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。