Thursday 14 June 2007

Useless Ruby StringBuilder

A little while ago, I wrote a StringBuilder class in Ruby in my lunch break, roughly based on the one in the .NET Framework, but simpler. I have known for a while that using StringBuilder is a much quicker way of concatening strings than just using +. I'm talking about C# indeed, and expect VB.Net to need the same.

I'm still fairly new to Ruby, so I thought I would give it a go there. I didn't find a StringBuilder class available, so I wrote a simple one. I looked a bit further and found there are two ways to concatenate strings in Ruby, using + and <<.

I added a bit of benchmarking code, and lo and behold, my StringBuilder class is lightning fast compared to the + method....
[with 100,000 iterations]
user system total real
stringbuilder: 0.172000 0.000000 0.172000 ( 0.172000)
string<<: 0.094000 0.000000 0.094000 ( 0.094000)
string+=: 14.703000 3.860000 18.563000 ( 18.734000)
But it is obvious << is a much better choice. Blimey, look at that. That's about 200 times faster than += ! No wonder there is no StringBuilder class provided with the Ruby core.
[with 1,000,000 iterations]
user system total real
stringbuilder: 1.610000 0.031000 1.641000 ( 1.656000)
string<<: 1.156000 0.000000 1.156000 ( 1.156000)

[with 10,000,000 iterations]
user system total real
stringbuilder: 17.672000 0.140000 17.812000 ( 17.953000)
string<<: 10.047000 0.047000 10.094000 ( 10.343000)
I had to remove the += case in these last two reports as my script wouldn't have returned before my lunch break was over!
require "benchmark"
include Benchmark

class Stringbuilder
def initialize(s)
@s=[s]
end

def <<(s)
@s << s
end

def to_s
@s.join("")
end
end

TESTS=100000

bm(14) do |test|
test.report("stringbuilder:") do
x=Stringbuilder.new("bla")
TESTS.times { |i|
x << "x"
}
z = x.to_s
end
test.report("string<<:") do
y="bla"
TESTS.times { |i|
y << "x"
}
z = y.to_s
end
test.report("string+=:") do
y="bla"
TESTS.times { |i|
y += "x"
}
z = y.to_s
end
end