[ruby-list:49458] Re: 【質問】定数の文字列展開について

From: 俊(とし) <toshio.otaguro@...>
Date: 2013-06-08 20:22:25 UTC
List: ruby-list #49458
ありくい様,

コメントありがとうございました.やはり,定数であっても実行時に展開されるのですね.定数であれば,スクリプトのコンパイル時に展開してくれても良さそうな気がしますが,Ruby
の定数は再代入もできるようなので,そういう仕様なのでしょう.

私の疑問だった (5)(6)
が微妙に遅いのも,定数の参照のオーバーヘッドと解釈できることも納得しました.このあたりは,スクリプティングのノウハウの一つになりそうな気がします.


2013年6月9日 2:51 Kazuhiro Shibutani <arikui.ruby@gmail.com>:

> ありくいという者です。
>
> > 定数の文字列を正規表現の中で展開するタイミングは,Ruby
> > スクリプトのコンパイル時ではなくて,実行時なのでしょうか?
>
> その通りです。
> Rubyはとても動的な言語なので、実行してみるまでほとんど式の値と
> いうのはわかりません。oオプションは最初の一回の評価をキャッシュ
> するような動作をするので、一回は式展開します。
>
>  正規表現リテラル - Ruby 2.0.0 リファレンスマニュアル
>  http://doc.ruby-lang.org/ja/2.0.0/doc/spec=2fliteral.html#regexp
>
> 対して、正規表現リテラルはスクリプトのコンパイル時に解決できるので
> (1)(2)と(4)で実行コストに差が出るのは自然なのです。
> (1)(2)は実行のたびにRegexpオブジェクトを生成しているわけではありません。
>
> > また,予め正規表現をコンパイルしておいた case(5), (6) よりも,
> > 正規表現をリテラルのままにしてある case(1), (2)
> > のほうが速いのも腑に落ちません.
>
> これらも、コンパイル時に解決される(1)(2)が一番実行コストが安いことによる
> ものです。
> (あと(5)(6)は微妙にn回定数参照しているオーバーヘッドが地味に効いているような
> 気がします)
>
>
>
>
> 2013年6月8日 9:38 俊(とし) <toshio.otaguro@gmail.com>:
>
> > 非常に初歩的な質問で申し訳ないのですが,定数の文字列を正規表現の中で展開するタイミングは,Ruby
> > スクリプトのコンパイル時ではなくて,実行時なのでしょうか?
> >
> > # --------------------
> > n = 1000000
> > line0 = "abc | 123"
> > C0 = '\s\|\s'
> > R0 = Regexp.new(/\s\|\s/)
> > R1 = Regexp.new(C0)
> >
> > tstart = Time.now()
> > n.times { /\s\|\s/ =~ line0 }
> > tstop = Time.now()
> > $stderr.print "case(1) ", (tstop - tstart), "\n"
> >
> > tstart = Time.now()
> > n.times { /\s\|\s/o =~ line0 }
> > tstop = Time.now()
> > $stderr.print "case(2) ", (tstop - tstart), "\n"
> >
> > tstart = Time.now()
> > n.times { /#{C0}/ =~ line0 }
> > tstop = Time.now()
> > $stderr.print "case(3) ", (tstop - tstart), "\n"
> >
> > tstart = Time.now()
> > n.times { /#{C0}/o =~ line0 }
> > tstop = Time.now()
> > $stderr.print "case(4) ", (tstop - tstart), "\n"
> >
> > tstart = Time.now()
> > n.times { R0 =~ line0 }
> > tstop = Time.now()
> > $stderr.print "case(5) ", (tstop - tstart), "\n"
> >
> > tstart = Time.now()
> > n.times { R1 =~ line0 }
> > tstop = Time.now()
> > $stderr.print "case(6) ", (tstop - tstart), "\n"
> > # --------------------
> >
> > 上記のサンプルプログラムをRuby-2.0.0p208 (rev. 41155) で走らせると,結果は以下のようになります.
> >
> > case(1) 0.311638805
> > case(2) 0.312117764
> > case(3) 8.188489523
> > case(4) 0.396936021
> > case(5) 0.330860272
> > case(6) 0.330536675
> >
> > ここで疑問は,case(3)
> > が異常に遅いのは,実行時に毎回,定数であっても文字列を展開しているのだろうと推測しますが,ちょっと腑に落ちないのは,case(4) で o
> > オプションを付けても case(1), (2) よりもかなり遅いという点です.
> >
> > また,予め正規表現をコンパイルしておいた case(5), (6) よりも,正規表現をリテラルのままにしてある case(1), (2)
> > のほうが速いのも腑に落ちません.
> >
> > ちなみに Ruby-1.9.3p194 (rev. 35410) で走らせると以下のような結果になります.特に,case(3)
> > が上記よりは速いのが目立ちますが,これは正規表現エンジンが異なるからでしょうか?
> >
> > case(1) 0.30897303
> > case(2) 0.308756529
> > case(3) 3.997449237
> > case(4) 0.356132962
> > case(5) 0.336724425
> > case(6) 0.33666136
> >
> > ご教示いただければ幸いです.
> > --
> > 俊(とし)
> >
> > <http://griffin.cocolog-nifty.com/lakesidedairy/>
> >
>

-- 
俊(とし)

In This Thread

Prev Next