In Rails applications, we often pay less attention to performance because our data is still small, not enough to slow down the system.
But in some large projects, improving performance becomes very important. The first thing is we will have to eliminate N + 1 queries, after removal is complete and our system is still slow, we need to use Data Cache to optimize.
1. How it works
Model Caching works by using a cache to store data on the first page load. In subsequent visits, the data is only retrieved from the cache, not the query from the DB anymore. Since then our site will improve performance, users will feel our site faster and smoother.
Caching here I use Redis. Because redis is an in-memory data structures store, it stores data structures and key-values in the main memory (RAM). This has made Redis fast processing speed and data recovery almost instantaneously
2. Caching with Redis
2.1 Initializing Project
We will create a small demo application called MyPost as follows:
1 2 3 | rails new MyPost rails g scaffold Post content:string |
We will use gem “Faker” to fake data
1 2 | gem "faker" |
Then run bundle install
and Import the data as follows:
1 2 3 4 | 100000.times do Post.create(content: Faker::Lorem.paragraph) end |
Here I create 100k records, you can also create smaller. And bh will run the rails db:seed
command
Modify the router so that the root page points to our correct Post page
1 2 3 4 | #routes.rb root "posts#index" |
When the page loads, it will produce the following result
ActiveRecord takes 60.6ms to execute sql statement and Views takes 21941.0ms to display. Thus we can see that our application runs very slowly. Come on, let’s optimize them.
2.2 Initialize Redis
We will install redis via this command
1 2 | sudo apt-get install redis |
Or see the detailed instructions here
After installing redis, we start it
1 2 | redis-server |
To connect Redis to the application, we will have to add some gems to Gemfile , then run bundle install
1 2 3 4 5 | gem "redis" gem "redis-namespace" gem "redis-rails" gem "redis-rack-cache" |
2.3 Caching
We reinstall the application.rb file to be able to cache the application with redis
1 2 3 4 5 6 7 8 | module MyPost class Application < Rails::Application [...] config.cache_store = :redis_store, 'redis://localhost:6379/0/cache', {expires_in: 90.minutes} [...] end end |
We need to create a Redis instance so we can call it anywhere in the Rails application
1 2 3 4 | #initializers/redis.rb $redis = Redis::Namespace.new "demo-redis", redis: Redis.new |
We will modify the index method in posts_controller.rb as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # posts_controller.rb def index @posts = fetch_post respond_to do |format| format.json {render json: @posts, status: :ok} end end private def fetch_post posts = $redis.get "posts" if posts.nil? posts = Post.all.to_json $redis.set "posts", posts end JSON.load posts end |
Let’s run again and see what results
We see Views only takes 13ms to display and ActiveRecord is 0ms, so the server does not take time to query data, instead of taking data from Redis so our application runs very fast.
3. Some notes
3.1 Handling when redis error
We need to catch exceptions for cases like this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | # posts_controller.rb def fetch_post begin posts = $redis.get "posts" if posts.nil? posts = Post.all.to_json $redis.set "posts", posts end posts = JSON.load posts rescue => error puts error.inspect posts = Post.all end posts end |
3.2 Data after update or delete
In case the data after updating or deleting, the data in redis has not been updated yet. So we need to update the data in redis when this is the case
1 2 3 4 5 6 7 8 9 10 11 | #Post.rb class Post < ApplicationRecord after_save :clear_cache private def clear_cache $redis.del "posts" end end |
Caching is a great technique to increase the performance of our application. Hope the article will help you have a look at caching
Refer
http://www.victorareba.com/tutorials/speed-your-rails-app-with-model-caching-using-redis https://www.sitepoint.com/rails-model-caching-redis/