Help us understand the problem. What is going on with this article?

ダブルクオートとシングルクオートの速度差は(ほぼ)ない

More than 3 years have passed since last update.

Perlでは、パフォーマンスを重視するなら、シングルクオートを使うことが通説らしい(5.8時点。最近は知らない)。
それ以来、シングルクオートが文字列になる言語では基本的にシングルクオートを使うようにしている。
が、こんな記事を見つけてしまった。

Rubyのシングルクォートとダブルクォートは、実行速度には差が無い : /var/log/maeda.log
http://vividtone.seesaa.net/article/84396945.html

ダブルクオートの式展開はコンパイル時に解決されるらしい。
これを実際に検証したブログはないようだったので、検証してみた(Ruby 2.0 on OSX 10.10)。
irb上でRubyVM::InstructionSequence.compile(...).to_aを使うとバイトコードを表示できるので、これを読めば良いということになる。

検証に使う文字列はこれにした。

%q(x=5;puts "aaa #{x**3}")

irbに読ませると"x=5;puts \"aaa \#{x**3}\""となり、展開はされていないことがわかる。

irb> RubyVM::InstructionSequence.compile(%q(x=5;puts "aaa #{x**3}")).to_a
=> ["YARVInstructionSequence/SimpleDataFormat", 2, 0, 1, {:arg_size=>0, :local_size=>2, :stack_max=>4}, "<compiled>", "<compiled>", nil, 1, :top, [:x], 0, [], [1, [:trace, 1], [:putobject, 5], [:setlocal_OP__WC__0, 2], [:trace, 1], [:putself], [:putobject, "aaa "], [:getlocal_OP__WC__0, 2], [:putobject, 3], [:opt_send_simple, {:mid=>:**, :flag=>256, :orig_argc=>1, :blockptr=>nil}], [:tostring], [:concatstrings, 2], [:opt_send_simple, {:mid=>:puts, :flag=>264, :orig_argc=>1, :blockptr=>nil}], [:leave]]]

確かにコンパイル時点で式が展開されている。

念のため、シングルクオート版も見てみた。

irb> RubyVM::InstructionSequence.compile(%q(x=5;puts 'aaa '+(x**3).to_s)).to_a
=> ["YARVInstructionSequence/SimpleDataFormat", 2, 0, 1, {:arg_size=>0, :local_size=>2, :stack_max=>4}, "<compiled>", "<compiled>", nil, 1, :top, [:x], 0, [], [1, [:trace, 1], [:putobject, 5], [:setlocal_OP__WC__0, 2], [:trace, 1], [:putself], [:putstring, "aaa "], [:trace, 1], [:getlocal_OP__WC__0, 2], [:putobject, 3], [:opt_send_simple, {:mid=>:**, :flag=>256, :orig_argc=>1, :blockptr=>nil}], [:opt_send_simple, {:mid=>:to_s, :flag=>256, :orig_argc=>0, :blockptr=>nil}], [:opt_plus, {:mid=>:+, :flag=>256, :orig_argc=>1, :blockptr=>nil}], [:opt_send_simple, {:mid=>:puts, :flag=>264, :orig_argc=>1, :blockptr=>nil}], [:leave]]]

"aaa "が:putobjectから:putstringになっているので若干速くなっている可能性があるが、逆に命令数が増えてしまった。

式展開がない場合でも、実行時点では、:putobjectと:putstringの差しかない。
というわけで、ダブルクオートとシングルクオートの速度差は体感できるほどではないことがバイトコードから理解できた。

追伸:
あくまでYARVが対象なので、Ruby 1.8ではどのような扱いなのかは依然としてはっきりしないが、もはや気にする必要はないと思われる。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away