zomです。 仕事上でifを連発している過去の自分のソースを見て、caseで書き直したほうが見やすいのでは?と思い、リプレイスしてみました。 やってみたものの「まぁ、多少見やすくなったかな?」程度の結果でした。 肝心なのは「多少の見栄え < 速度」だと思いますので、速度が落ちていないかどうかが問題です。 そこで思ったのですが、ifとcaseで速度に違いはあるのか?ということでした。
普通に考えれば演算子がifは==で比較して、caseは===で、とか、そもそもの比較対象によって速度は変わるので一概に言えないのではないだろうか、というのが自分の考えです。 それでも百聞は一見にしかずだろ、ということでやってみます。
あ、その前にググってみたらRubyのifとcaseでは、どちらが速いかこちらですでにやってました。 でも、バージョンも書いてないし、一応試してみます。
a="d" n=1000000 st=Time.now n.times{ if a=="a" elsif a=="b" elsif a=="c" else end } puts "if Times: #{Time.now-st}s" st=Time.now n.times{ case a when "a" when "b" when "c" else end } puts "case Times: #{Time.now-st}s"
上記のサイトのをそのまま使わせていただきます。
Ruby1.9.3で試してみます。
$ ruby --version ruby 1.9.3p327 (2012-11-10 revision 37606) [x86_64-linux] $ ruby sample.rb if Times: 0.830324594s case Times: 0.217178136s $ ruby sample.rb case Times: 0.194395472s if Times: 0.66237522s
ん?上記のサイトとだいぶ違う結果が…。 まさか実行順が違う?と思って2回めの前にifとcaseの順番を変えてますが、当然そういうわけではなさそう。
じゃあRuby2.0ならどうだろう?
$ ruby --version ruby 2.0.0p0 (2013-02-24 revision 39474) [x86_64-linux] $ ruby sample.rb if Times: 1.780754s case Times: 0.435103s $ ruby sample.rb if Times: 1.78981s case Times: 0.431919s
おー…。
ちなみに1.9と2.0ではサーバが別物なので、そこでの数値は比較できないです。(rbenvがあるので、やろうと思えばできますが面倒…) いずれにしてもRuby1.9と2.0だとcaseのほうが3倍~4倍程度速いっぽい?
確かcaseの内部では===(case比較演算子)が使われてるはず。 じゃあif文の==をcase比較演算子に書き換えたら数値が近づくかな?と思い試してみました。
a="d" n=1000000 st=Time.now n.times{ if a==="a" # ===に変えました elsif a==="b" # ===に変えました elsif a==="c" # ===に変えました else end } puts "if Times: #{Time.now-st}s" st=Time.now n.times{ case a when "a" when "b" when "c" else end }
$ ruby sample.rb if Times: 2.087001s case Times: 0.425709s $ ruby sample.rb if Times: 2.009104s case Times: 0.435917s
さっきの1.8sくらいから0.2sくらい悪化してますけど!? まぁ、case比較演算子のほうが型までみたり、時間がかかるイメージはありますが…じゃあなんでcaseのほうが速い?
と、謎は謎のままです。 何事も自分で計測して確かめるのが一番ですね。(無難なまとめ)