Why Bullet Gem?
For this Rails optimization, we'll focus on optimizing repeated SQL calls to retrieve objects associated with many relationships: N+1 queries problem. The solution to such an issue is an eager loading association. Unoptimized N+1 affected code takes a significantly longer time as N times additional SQL calls are needed.
But, we should be careful when using that eager loading approach. This because unused eager loading can deteriorate our Rails app performance instead of improving it.
It's where the Bullet gem comes in handy. This gem will help us to find where:
- the N+1 queries problem is happening.
- the eager loading associate is unused.
How to use Bullet Gem?
This depends on the current application's state. In our case, we do these:
- Add the bullet gem into Gemfile.
- Define a new Rails environment called optimization.
- Configure it to install the gem for that environment only
- Run the Rails app with that environment
1. Add the Bullet gem into Gemfile.
Here, we use its latest version which is 6.1.0. After adding that into your Gemfile, you may run the usual bundle install
2. Define a new environment
We don't want this gem to run on our usual development environment. We don't want it in the production environment either. So, we define a new environment to run this gem. We call it optimization.
So, we add a new environment under the config/environments folder. We name it optimization.rb. Inside this new environment, we add the bullet gem configurations.
Here's what are they meaning:
- Bullet.enable - We tell it to enable the Bullet gem in this optimization environment so we set it to be true.
- Bullet.alert - This will let the gem show javascript alert on any of our application pages, where there is an N+1 queries problem or unused eager loading problem or both of them.
- Bullet.bullet_logger - Set if Bullet gem should log to the Bullet log file (Rails.root/log/bullet.log)
- Bullet.console - Set if the Bullet gem should log the warning message on your browser's javascript console.
- Bullet.rails_logger - Set whether Bullet gem should write it to the Rails log file as well.
- Bullet.add_footer - If true, it will show on the footer of the warning details (if any) to every app's page.
There are many other configurations you may want to explore at the official Bullet doc.
Please don't forget to add the environment to the webpacker.yml!
3. Configure to install Bullet on optimization environment only
This is pretty straightforward. You only need to update Gemfile and put the Bullet gem inside the group block. Just like this one
4. Run the Rails app with that environment
There are many ways to do this. But, we suggest to run it with rails server command like this:
bundle exec rails server -e optimization
You may get hints of optimization on a page/site you visit!
Example of Bullet Message - AVOID eager loading detected in this case... will optimize the point.
Conclusions
- N+1 queries problem will slow down our Rails app. But implementing eager loading blindly won't help either.
- This gem is NOT a silver bullet. It won't fix all of the N+1 queries problems on your app. It will neither magically remove the unused eager loading query. It's just telling you and you still need to update your app codes based on its suggestions.
- Bullet gem will show you in details, which part of your Rails app that:
- has an N+1 queries problem. In this case, it will tell you to add eager loading.
- has an unused eager loading query. This one will suggest you remove the eager loading