Have you ever heard Memoization? In this article you will get an introduction of Memoization. You will learn what it is, how you can use it to speed up your code.
What is Memoization?
Memoization is the process of storing a computed value to avoid duplicated work by future calls.
What are Memoization used for?
- Perform some work
- Store the work result
- Use stored results in future calls
Using
In Ruby the most common pattern for using Memoization is the conditional assignment operator: ||=
.
Example
In Rails if you’ve ever worked with a user login system, you really family with the pattern of loading the current_user
in the application_controller.rb
:
1 2 3 |
|
Within each request in a Rails application you will usually see multiple calls to current_user
that means User.find
method is run multiple times.
In this case, we know the problem is because there are multiple calls to current_user
occurring. Let’s fix this code by introducing Memoization into the current_user
method and storing the result of User.find
method by using conditional assignment to an instance variable:
1 2 3 |
|
Well, there are no more calls to rebuild the User
object each time current_user
method is called.
When should you memoize?
- When you’ve got duplicated database
- When you’ve got expensive calculations
- When you’ve got repeated calculations that don’t change
When shouldn’t you memoize
- Memoization shouldn’t be used with methods that take parameters:
1 2 3 4 5 6 7 8 |
|
- Memoization shouldn’t be used with methods that use instance variables:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Memoization conditional assignment have problem when return nil or false in Ruby
If you are not clear in using conditional assignment it can bite you, let try code below:
1 2 3 4 5 6 7 8 9 10 11 |
|
Suprised that “printing” was printed twice? Conditional assignment is always going to run if the instance variable @print
is false or nil.
Well, we can solve the problem by using defined?
:
1 2 3 4 5 6 7 8 9 10 |
|
Memoization conditional assignment have problem when return nil or false in Rails
1 2 3 |
|
What’s happen if User.find
return nil? Conditional assignment is always going to run and current_user method is always going to call if the instance variable @print
is false or nil.
Well, we can fix the problem by using the Memoizable API in Rails:
1 2 3 4 5 6 7 |
|
Or we can use Memoizable to fix this problem
So far so good, I hope this article comes in handy for some of you who haven’t heard of memoization yet or who just didn’t really understand what’s going on there. :)