在Ruby中构建字符串的最快方法是什么?

And*_*imm 15 ruby string optimization

Ternary运算符中,一个想要加入["foo", "bar", "baz"]逗号和"and"的人引用了Ruby Cookbook的话

如果效率对您很重要,则在将项目附加到现有字符串时不要构建新字符串.[等等] ...使用str << var1 <<''<< var2代替.

但这本书写于2006年.

<<在Ruby的所有主要实现中,使用appending(ie )仍然是在给定一个较小字符串数组的情况下构建大字符串的最快方法吗?

Phr*_*ogz 23

尽可能使用Array#join,String#<<何时不能使用.

使用的问题String#+是它必须创建一个中间(不需要的)字符串对象,同时String#<<改变原始字符串.下面是连接1000个与字符串的时间的结果(以秒计)", "的1000倍,通过Array#join,String#+String#<<:

Ruby 1.9.2p180      user     system      total        real
Array#join      0.320000   0.000000   0.320000 (  0.330224)
String#+ 1      7.730000   0.200000   7.930000 (  8.373900)
String#+ 2      4.670000   0.600000   5.270000 (  5.546633)
String#<< 1     1.260000   0.010000   1.270000 (  1.315991)
String#<< 2     1.600000   0.020000   1.620000 (  1.793415)

JRuby 1.6.1         user     system      total        real
Array#join      0.185000   0.000000   0.185000 (  0.185000)
String#+ 1      9.118000   0.000000   9.118000 (  9.118000)
String#+ 2      4.544000   0.000000   4.544000 (  4.544000)
String#<< 1     0.865000   0.000000   0.865000 (  0.866000)
String#<< 2     0.852000   0.000000   0.852000 (  0.852000)

Ruby 1.8.7p334      user     system      total        real
Array#join      0.290000   0.010000   0.300000 (  0.305367)
String#+ 1      7.620000   0.060000   7.680000 (  7.682265)
String#+ 2      4.820000   0.130000   4.950000 (  4.957258)
String#<< 1     1.290000   0.010000   1.300000 (  1.304764)
String#<< 2     1.350000   0.010000   1.360000 (  1.347226)

Rubinius (head)     user     system      total        real
Array#join      0.864054   0.008001   0.872055 (  0.870757)
String#+ 1      9.636602   0.076005   9.712607 (  9.714820)
String#+ 2      6.456403   0.064004   6.520407 (  6.521633)
String#<< 1     2.196138   0.016001   2.212139 (  2.212564)
String#<< 2     2.176136   0.012001   2.188137 (  2.186298)
Run Code Online (Sandbox Code Playgroud)

这是基准测试代码:

WORDS = (1..1000).map{ rand(10000).to_s }
N = 1000

require 'benchmark'
Benchmark.bmbm do |x|
  x.report("Array#join"){
    N.times{ s = WORDS.join(', ') }
  }
  x.report("String#+ 1"){
    N.times{
      s = WORDS.first
      WORDS[1..-1].each{ |w| s += ", "; s += w }
    }
  }
  x.report("String#+ 2"){
    N.times{
      s = WORDS.first
      WORDS[1..-1].each{ |w| s += ", " + w }
    }
  }
  x.report("String#<< 1"){
    N.times{
      s = WORDS.first.dup
      WORDS[1..-1].each{ |w| s << ", "; s << w }
    }
  }
  x.report("String#<< 2"){
    N.times{
      s = WORDS.first.dup
      WORDS[1..-1].each{ |w| s << ", " << w }
    }
  }
end
Run Code Online (Sandbox Code Playgroud)

在RVM下在Ubuntu上获得的结果.来自Windows上RubyInstaller的Ruby 1.9.2p180的结果与上面显示的1.9.2类似.