There are many tools out there that help you improve the performance of you rails apps. In this post I want to introduce you to some of them that help me out most of the time. What I suggest you to do when profiling your rails app is keeping score of the times that you improve. In your rails console log you will see the time the rending took (split into view and activerecord and total time).
First thing you should be doing is a pagination. It does not matter how fast your application performs when you have too many records that you are loading. So have a look at any of the good pagination gems out there like will_paginate or kaminari. A good effect is that your application becomes not only faster but your usability also improves a lot!
Next try to improve you indexes for your rails app. Make sure to always index your foreign keys in your database. This creates a foreign key without an index:
rails g migration CreateCalendarEvents user_id:integer
This is the better approach which automatically creates add the index to the migration file:
rails g migration CreateCalendarEvents user:references
Here you see a migration file with the reference to the user model and an automatically created index, with index: true.
Sometimes you forget to index all foreign keys. There is a good gem to find out if you did that called lol_dba. With
rake db:find_indexes it will find out if there are any indexes missing and create you directly a migration file.
The bullet gem will give you the help with N+1 Queries and Counter Caches.
The N+1 Query Problem is when you for example loop 10 client objects in your view and access the address of the client that is in a different model. Example from here.
clients = Client.limit(10) clients.each do |client| puts client.address.postcode end
The problem lies within the total number of queries executed. The code executes 1 (to find 10 clients) + 10 (one per each client to load the address) = 11 queries in total. The solution to this problem is adding an
includes in your controller. So in the example write
clients = Client.includes(:address).limit(10) clients.each do |client| puts client.address.postcode end
The bullet gem makes sure you do not forgot about the N+1 Queries and gives you a warning when you do.
It will also advice you to use counter caches sometimes. Once you have some counts of records on a model e.g. a
Class has_many Students, you want to show that number. Rails can automatically keep the count of the Students to a class via a counter_cache column. Read more on this here.
Rack Mini-Profiler together with flamegraph help you see in detail about the queries performed on a page. You can use it both in development mode and in production. It shows the rendering time of the page at the left upper corner of your screen. When you click on it you see more detailed data. . This is a very good way to see how long exactly your database queries take or the views to render.