It’s a well-known fact that interpreted languages are slower than compiled languages. Since Ruby was created to make programmers happy and make their work easier, it’s closer to the programmer than to the machine. Ruby, like other scripting languages, abstracts away a lot of technical details and provides the user with a high-level API which is user-friendly.

However, in this day where everyone is building applications that can scale, it’s very important to know some of the performance tweaks to make your Ruby code run faster; without of course, spending voluminous time on it. Like Knuth said, ‘Premature optimization is the root of all evil.’ The tricks we’re going to point out come in handy and no extra work is required on part of the programmer.

1) Interpolated Strings are faster than Concatenation:

Concatenation is usually slower than string interpolation. String interpolation is done when we write Ruby code inside #{}. Like so,

Non-optimized:

puts “This ” << str1 << “ is slower ” << str2

Optimized:

puts “This #{str1} and #{str2} is faster”

 

2) Try to use destructive operations:

While we can use non-destructive operators just as well, there is considerable advantage that we can leverage when using destructive operators.

Non-optimized:

str = "string to gsub"
str = str.gsub(/to/, 'copy') # duplicate string and reassigns it. That's bad!

Optimized:

str.gsub!(/to/, 'copy') # same effect, but no object duplication. Yoohoo!

 

3) Don’t forget to Benchmark:

Benchmarking is a well-known technique to gauge the performance of a system. It gives you a pretty good idea of where the bottlenecks are, and the code which is impacting performance adversely.

Example:

require 'benchmark'

n = 100000

Benchmark.bm do |x|
  x.report('copy') { n.times do ; h = {}; h = h.merge({1 => 2}); end }
  x.report('no copy') { n.times do ; h = {}; h.merge!({1 => 2}); end }
end

4) Clever Concatenations:

Avoid using += to concatenate strings in favor of << method. The result is absolutely the same: add a string to the end of an existing one.

Example:

str1 = "first"
str2 = "second"

str1.object_id # => 16241320
str1 += str2 # str1 = str1 + str2

str1.object_id # => 16241240, id is changed
str1 << str2
str1.object_id # => 16241240, id is the same


 

When you use += ruby creates a temporal object which is result of str1 + str2. Then it overrides str1 variable with reference to the new built object. On other hand << modifies existing one.

5) Use the right iterators:

Iterators are a blessing in Ruby that allow us to iterate over an object in a single line. It’s important, though, to make sure that we’re using the right iterator that both fulfills our purpose and is reasonably fast. Avoid using dumb iterators!

Example:

collection.map(&:field)                                 # faster

collection.map { |elem| elem.field }                    # slower

collection.reduce([]) { |acc, elem| acc << elem.field } # slowest

To conclude, Ruby is a great language and greatly simplifies the programmer’s effort. If you know tricks and techniques like above then not only will that make your code run faster but it will also help you appreciate different languages, what makes them unique, how they manage memory; all of which will enable you to make a more informed choice for your projects.