Speed up Ruby on Rails product

The performance of a web application is crucial so what optimization techniques helped me improve the performance of my app?

Tips to optimize the performance of a Ruby on Rails app

Eliminate the N+1 query problem

One of the most frequent causes of slow app performance is the N+1 query problem faced by most Ruby on Rails applications.

N+1 means one line of code results in more queries then expected

As a project grows, this problem only compounds. To avoid this problem, we need to cut the number of independent database queries. Eager-load associated relations is the best solution in this case.

Example:

We just need easily use includes to eagerly loaded the associated category records to fix the problem.

articles = Articles.all.includes(:category)

It’s easy to fix but hard to find out where N+1 issues placed in a ton of codes. There is a useful gem to detect N+1 problem Bullet.

Use size instead of length

ActiveRecord doesn’t define a length property. This means

Size completes the process 10 times faster and consume less memory then length. With length, all articles are loaded and converted into an array before they are counted.

Ruby also provide the count method but the size method is more useful because if the collection is loaded, it counts its elements with no additional query.

Use pluck instead of map

Pluck is a shortcut that helps us choose one or several attributes.

Map loads objects into memory and gets an attribute.

Pluck return an attribute without loading objects into memory.

Pluck costs less time and memory use by Ruby on Rails

Add indexes to your database

The more tables expand, the slower the app gets.

Without indexes, the database engine need to check every record in the table until it finds a match.

With indexes, the lookup will check only specific records so it will be a lot faster.

Before adding an index, it’s important to know if searches or updates will be performed more often. Indexes speed up searches but slow down updates

Example

It’s also important to add indexes to foreign keys, joint tables and polymorphic relationships for faster lookup. When we need to remove an index and the table at the same time, we have to remove the index first.

Use background job

It’s important to use background processing to boost up the performance. Statistics calculations, reports generation, video processing, emails sending and similar tasks that we can run periodically. Optimize the repetitive tasks by handling them automatically.

We use Sidekiq, the most popular open source gem, for this purpose. It uses Redis as its job management store, leveraging its speed. Sidekiq also provides a dashboard that shows all our job queues and their processing states.

Caching

This is a big topic because there are my types of caching that can be applied in different cases. I will write about it in another post.

Upgrade Ruby

New Ruby or Rails versions tend to bring performance improvements but most customers are not ready to pay for upgrading new version because they only see their products are running well and want to have new features as soon as possible.

In summary, I’m not the person who can think out all of these above tips. I just read some articles somewhere and applied to my projects successfully. You should pick solutions that suit for your projects instead. Don’t apply them mechanically.