String concatenation in Ruby
Posted by Jonas Elfström Mon, 01 Feb 2010 23:04:00 GMT
There's no StringBuilder
class in Ruby because the String class has the << for appending. The problem is that not every Ruby programmer seems to be aware of it. Recently I've seen +=
being used to append to strings where <<
would have been a much better choice.
The problem with using +=
is that it creates a new String instance and if you do that in a loop you can get really horrible performance.
If you are dealing with an array you don't even have to use <<
because Array#join is even faster and shows intent in a nice way.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
require 'benchmark' array_of_rnd_strings=(0...262144).map{65.+(rand(25)).chr} .join.scan(/.{1,8}/m) Benchmark.bm do |benchmark| benchmark.report do str=array_of_rnd_strings.join end benchmark.report do str2="" array_of_rnd_strings.each do |s| str2<<s end end benchmark.report do str3="" array_of_rnd_strings.each do |s| str3+=s end end end |
user | system | total | real |
0.030000 | 0.000000 | 0.030000 | ( 0.027184) |
0.160000 | 0.010000 | 0.170000 | ( 0.190277) |
106.020000 | 0.300000 | 106.320000 | (113.457793) |
The performance of +=
was even worse than I imagined!
Sweet
BUT, if our strings are a discrete and well known collection (they are not in an array), the proper method in terms of speed is << or +, not join.
https://stackoverflow.com/questions/4402336/array-join-versus-string-concatenation-efficiency
@sapphire I’m not sure so I like that benchmark. The join example first builds an array and then joins. The concatenation example just concatenates “foobar” over and over. I can’t really map that to a real world scenario. If you can, please show me.
just wanted to clarify that there are are different cases. in your benchmarking, you measure the time to join an array, correctly concluding that the best method is join.
however, join is not the universal method to join strings (as a ruby noob may think), so i put the stackoverflow hyperlink.
so i you previously have strings in an array, then .join() them. but if you have a discrete well-known number of strings (a, b and c), join them as:
or
but never compose an array and then join them
hope my point is clear now :)
@sapphire Great explanation and I totally agree.