In another blog we compared string concatenation and interpolation in Ruby. In that blog, I claimed that “generally, you’ll want to stick with interpolation, as it’s quicker”. However, I didn’t really elaborate or provide any benchmarks. I noticed the post was linked in a reddit comment about this very topic, and I figured I needed to provide an update. So let’s do some benchmarking!

Benchmarking Setup

We can use benchmark from the Ruby standard library to easily accomplish our goal of comparing the performance of string concatenation and string interpolation in various scenarios.

Here’s the code for our test:

require 'benchmark'
  
e = "everybody"
w = "wang"
c = "chung"
t = "tonight"

## Test 1
concat = Benchmark.measure {
  5_000_000.times do
    string = "everybody" + " " + "wang" + " "  + "chung" + " " + "tonight"
  end
}

interp = Benchmark.measure {
  5_000_000.times do
    string = "#{"everybody"} #{"wang"} #{"chung"} #{"tonight"}"
  end
}


## Test 2
concat_var = Benchmark.measure {
  5_000_000.times do
    string = e + " " + w + " "  + c + " " + t
  end
}

interp_var = Benchmark.measure {
  5_000_000.times do
    string = "#{e} #{w} #{c} #{t}"
  end
}

## Test 3
concat_2 = Benchmark.measure {
  5_000_000.times do
    string = e + w
  end
}

interp_2 = Benchmark.measure {
  5_000_000.times do
    string = "#{e}wang"
  end
}

puts "Test #1:"
puts "concat: " + concat.to_s
puts "interp: #{interp}"
puts ""
puts "Test #2:"
puts "concat_var: " + concat_var.to_s
puts "interp_var: #{interp_var}"
puts ""
puts "Test #3:"
puts "concat_2: " + concat_2.to_s
puts "interp_2: #{interp_2}"

Test Rundown

So, in the above, we have three tests for both methods.

Test #1

In the standard case, we build the string “everybody wang chung tonight” with both methods. We use literal strings everywhere, not variables. These tests are in the code under concat and interp.

Test #2

Next, I wanted to see if there was any difference if the word strings for our phrase above were stored in variables. You can find these in the code as concat_var and interp_var.

Test #3

Lastly, I wanted to test a more modest case. I decided to concatenate two string varables, and interpolate one string variable into another literal string. You can find these under concat_2 and interp_2.

Hypothesis

My understanding is that concatenation takes longer because it makes an intermediate string for each addend. It would follow that if I were only concatenating a few strings, this affect would be less pronounced. It could be that concatenation beats interpolation in this case. Anyways, let’s run the code and find out.

Results

$ ruby ./benchmark_strings.rb | column -t

Test         #1:
concat:      3.112053  0.001308  3.113361  (  3.126933)
interp:      0.267799  0.000005  0.267804  (  0.269232)
Test         #2:
concat_var:  2.926580  0.000046  2.926626  (  2.936785)
interp_var:  1.801875  0.000000  1.801875  (  1.802651)
Test         #3:
concat_2:    0.442123  0.000000  0.442123  (  0.442274)
interp_2:    0.480152  0.000000  0.480152  (  0.482184)



$ ruby -v
ruby 2.6.5p114 (2019-10-01 revision 67812) [x86_64-linux]

So, what does this tell us?

  • Well, interpolation clearly wins with the longer string cases.
  • Variables vs. literals has a much more pronounced effect on interpolation than concatenation, with interpolation increasing in runtime by almost a full order of magnitude.
  • The 2-string cases are really really close for both. I ran this a few times and they were always close. It seemed like interpolation was more often lower, so I decided to increase the loop count and run it again with 50,000,000 iterations instead of 5,000,000:
$ ruby ./benchmark_strings2.rb | column -t

concat_2:            4.485134  0.000782  4.485916  (  4.487549)
interp_2:  	     4.760736  0.000000  4.760736  (  4.766114)

Well, what do you know?! I’m glad I ran it again, because this convinces me that concatenating 2 strings is faster than interpolating them. However, the difference is so negligible that I will probably just pick whatever I think is more readable.

Summary

So, in summary:

  • Interpolation is more efficient if you’re working with lots of strings.
  • If you just have a few strings, concatenation might be slightly faster.

Other things to consider:

  • Interpolation can be easier to extend/modify in the future.
  • Using interpolation for a literal and a variable is cool, but interpolating 2 variables looks silly if you aren’t including any literal strings:
"other ${thing} to"      # good
"other " + thing + " to" # tedious
string1 + string2        # good
"#{string1}#{string2}"   # tedious, unless you know you'll add something later