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.