在ruby中使用单引号和双引号是否有性能提升?

dim*_*mus 123 ruby syntax performance

你知道在ruby中使用双引号而不是单引号会在ruby 1.8和1.9中以任何有意义的方式降低性能.

所以,如果我输入

question = 'my question'
Run Code Online (Sandbox Code Playgroud)

比它快吗?

question = "my question"
Run Code Online (Sandbox Code Playgroud)

我想ruby试图弄清楚当遇到双引号时是否需要对某些东西进行评估,并且可能花费一些周期来做这件事.

Mar*_*une 103

总结:没有速度差异; 这个伟大的协作Ruby风格指南建议保持一致.我现在使用'string'除非需要插值(指南中的选项A)和它一样,但你通常会看到更多的代码"string".

细节:

从理论上讲,它可以在您的代码被解析时产生影响,但不仅一般不关心解析时间(与执行时间相比可忽略不计),在这种情况下您将无法找到显着差异.

重要的是,当被执行时它将完全相同.

对此进行基准测试只表明对Ruby的工作方式缺乏了解.在这两种情况下,字符串都将被解析为a tSTRING_CONTENT(参见源代码parse.y).换句话说,CPU在创建'string'或执行时将完成相同的操作"string".完全相同的位将以完全相同的方式翻转.对此进行基准测试只会显示不显着的差异以及其他因素(GC启动等); 记住,在这种情况下不会有任何区别!像这样的微观基准很难做到.看看我的宝石fruity是一个体面的工具.

请注意,如果存在表单的插值,则会"...#{...}..."将其解析为a tSTRING_DBEG,一堆tSTRING_DVAR表达式#{...}和final 表达式tSTRING_DEND.这只是在有插值的情况下,这不是OP的意思.

我以前建议你到处使用双引号(以后更容易实际添加#{some_var}),但我现在使用单引号,除非我需要插值\n,等等...我在视觉上喜欢它并且它稍微更明确,因为没有需要解析字符串以查看它是否包含任何表达式.

  • 似乎更重要的是微小的性能差异.双引号是! (3认同)
  • 这个答案应该标记为正确答案. (2认同)

zet*_*tic 85

$ ruby -v
ruby 1.9.3p0 (2011-10-30 revision 33570) [x86_64-darwin11.0.0]

$ cat benchmark_quotes.rb
# As of Ruby 1.9 Benchmark must be required
require 'benchmark'

n = 1000000
Benchmark.bm(15) do |x|
  x.report("assign single") { n.times do; c = 'a string'; end}
  x.report("assign double") { n.times do; c = "a string"; end}
  x.report("concat single") { n.times do; 'a string ' + 'b string'; end}
  x.report("concat double") { n.times do; "a string " + "b string"; end}
end

$ ruby benchmark_quotes.rb 

                      user     system      total        real
assign single     0.110000   0.000000   0.110000 (  0.116867)
assign double     0.120000   0.000000   0.120000 (  0.116761)
concat single     0.280000   0.000000   0.280000 (  0.276964)
concat double     0.270000   0.000000   0.270000 (  0.278146)
Run Code Online (Sandbox Code Playgroud)

注意:我已对此进行了更新,以使其适用于较新的Ruby版本,并清理标题,并在更快的系统上运行基准测试.

这个答案省略了一些关键点.请特别注意有关插值的其他答案以及使用单引号和双引号时性能没有显着差异的原因.

  • 测量的差异没有意义.只是顺序(因为垃圾收集)可以使重要的差异.''和```之间没有运行时区别,因为它们被解析为同一个东西. (9认同)

Tim*_*ite 35

没有人碰巧测量级联与插值:

$ ruby -v
ruby 1.8.7 (2008-08-11 patchlevel 72) [i686-darwin9.6.2]
$ cat benchmark_quotes.rb
require 'benchmark'
n = 1000000
Benchmark.bm do |x|
  x.report("assign single") { n.times do; c = 'a string'; end}
  x.report("assign double") { n.times do; c = "a string"; end}
  x.report("assign interp") { n.times do; c = "a string #{'b string'}"; end}
  x.report("concat single") { n.times do; 'a string ' + 'b string'; end}
  x.report("concat double") { n.times do; "a string " + "b string"; end}
end

$ ruby -w benchmark_quotes.rb 
      user     system      total        real
assign single  2.600000   1.060000   3.660000 (  3.720909)
assign double  2.590000   1.050000   3.640000 (  3.675082)
assign interp  2.620000   1.050000   3.670000 (  3.704218)
concat single  3.760000   1.080000   4.840000 (  4.888394)
concat double  3.700000   1.070000   4.770000 (  4.818794)
Run Code Online (Sandbox Code Playgroud)

特别要注意assign interp = 2.62VS concat single = 3.76.作为锦上添花,我还发现插值比'a' + var + 'b'空间更具可读性.


mad*_*lep 16

没有区别 - 除非您使用#{some_var}样式字符串插值.但是如果你真的这样做,你只能获得性能.

Zetetic的例子修改:

require 'benchmark'
n = 1000000
Benchmark.bm do |x|
  x.report("assign single") { n.times do; c = 'a string'; end}
  x.report("assign double") { n.times do; c = "a string"; end}
  x.report("assign interp") { n.times do; c = "a #{n} string"; end}  
  x.report("concat single") { n.times do; 'a string ' + 'b string'; end}
  x.report("concat double") { n.times do; "a string " + "b string"; end}
  x.report("concat interp") { n.times do; "a #{n} string " + "b #{n} string"; end}
end
Run Code Online (Sandbox Code Playgroud)

产量

               user       system     total    real
assign single  0.370000   0.000000   0.370000 (  0.374599)
assign double  0.360000   0.000000   0.360000 (  0.366636)
assign interp  1.540000   0.010000   1.550000 (  1.577638)
concat single  1.100000   0.010000   1.110000 (  1.119720)
concat double  1.090000   0.000000   1.090000 (  1.116240)
concat interp  3.460000   0.020000   3.480000 (  3.535724)
Run Code Online (Sandbox Code Playgroud)


Rei*_*chs 13

单引号可能比双引号略快,因为词法分析器不必检查#{}插值标记.取决于实现等.请注意,这是分析时成本,而不是运行时成本.

也就是说,实际的问题是,使用双引号字符串是否"以任何有意义的方式降低性能",答案是决定性的"否".性能差异非常小,与任何真正的性能问题相比,它完全无关紧要.不要浪费你的时间.

当然,实际插值是一个不同的故事.'foo'将快几乎快1秒"#{sleep 1; nil}foo".

  • +1注意到成本是在编译时而不是在运行时,所以上面基于基准的高评价答案是误导性的. (4认同)

Phi*_*ilT 8

以为我会添加1.8.7和1.9.2的比较.我跑了几次.差异约为+ -0.01.

require 'benchmark'
n = 1000000
Benchmark.bm do |x|
  x.report("assign single") { n.times do; c = 'a string'; end}
  x.report("assign double") { n.times do; c = "a string"; end}
  x.report("assign interp") { n.times do; c = "a #{n} string"; end}
  x.report("concat single") { n.times do; 'a string ' + 'b string'; end}
  x.report("concat double") { n.times do; "a string " + "b string"; end}
  x.report("concat interp") { n.times do; "a #{n} string " + "b #{n} string"; end}
end
Run Code Online (Sandbox Code Playgroud)

ruby 1.8.7(2010-08-16 patchlevel 302)[x86_64-linux]

assign single  0.180000   0.000000   0.180000 (  0.187233)
assign double  0.180000   0.000000   0.180000 (  0.187566)
assign interp  0.880000   0.000000   0.880000 (  0.877584)
concat single  0.550000   0.020000   0.570000 (  0.567285)
concat double  0.570000   0.000000   0.570000 (  0.570644)
concat interp  1.800000   0.010000   1.810000 (  1.816955)
Run Code Online (Sandbox Code Playgroud)

ruby 1.9.2p0(2010-08-18修订版29036)[x86_64-linux]

  user          system      total      real
assign single  0.140000   0.000000   0.140000 (  0.144076)
assign double  0.130000   0.000000   0.130000 (  0.142316)
assign interp  0.650000   0.000000   0.650000 (  0.656088)
concat single  0.370000   0.000000   0.370000 (  0.370663)
concat double  0.370000   0.000000   0.370000 (  0.370076)
concat interp  1.420000   0.000000   1.420000 (  1.412210)
Run Code Online (Sandbox Code Playgroud)


aqn*_*aqn 8

双引号的键入次数是单引号的两倍.我总是匆忙.我用单引号.:)是的,我认为这是"性能提升".:)

  • 即使IDE自动关闭报价,双引号仍然需要100%以上的键击.;-) (3认同)