Tips for Writing Fast Rails: Part 2

Tips for Writing Fast Rails: Part 2

Some time ago we wrote a couple of Tips for Writing Fast Rails. It was about time we wrote part two so here it is!

In this article we will focus on the use of ActiveRecord::Calculations. To show the difference in execution time between doing the math in the database vs. in Ruby we will use benchmark-ips. Keep in mind that the table used in these examples has thousands of records, so the difference should be quite noticeable.

Prefer ActiveRecord::Calculations#sum instead of Enumerable#sum

Usually in Rails applications we find many references to Enumerable::sum for summing values. This is a common mistake because ActiveRecord::Calculations provides a way to do this without loading a bunch of ActiveRecord objects in memory. If you want to perform mathematical operations for a set of records following the Rails way, ActiveRecord::Calculations is the best way to do them in the database.

Benchmark.ips do |x|"SQL sum") do
  end"Ruby sum") do
    # Same as: { |loan| loan.balance }.sum

# Comparison:
#            SQL sum:        7.89 i/s
#           Ruby sum:        0.03 i/s - 209.85x  slower

Prefer ActiveRecord::Calculations#maximum instead of Enumerable#max

As we explained above, to perform better with calculations you should use ActiveRecord::Calculations methods whenever is possible.

Benchmark.ips do |x|"SQL max") do
  end"Ruby max") do

# Comparison:
#              SQL max:      541.9 i/s
#             Ruby max:        0.5 i/s - 1113.47x  slower

Prefer ActiveRecord::Calculations#minimum instead of Enumerable#min

Benchmark.ips do |x|"SQL min") do
  end"Ruby min") do

# Comparison:
#              SQL min:      533.3 i/s
#             Ruby min:        0.5 i/s - 1017.21x  slower


As you can see, changing the way that you solve the problem can have significant performance improvements. Don't forget to take a look at the ActiveRecord::Calculations documentation to see all the available methods.

Get the book