Table of contentsClick link to navigate to the desired location
This content has been automatically translated from Ukrainian.
Memoization — is an optimization technique that involves caching the results of function executions to avoid repeated calculations on subsequent calls. This is especially useful for expensive operations (e.g., database queries, complex computations, or working with APIs).
Why this name?
The term "memoization" comes from the English word "memo" (note, reminder) and the Latin root "memor-" (to remember). This suggests that the function "remembers" (caches) its results to avoid repeated calculations.
This term was first used by Donald Michie, a British scientist in the field of artificial intelligence, back in 1968. He described the technique where computed values are stored for future use.
Why not just "caching"?
Memoization is a specific type of caching.
- Memoization typically caches function results at the instance level of an object or within a single process.
- Caching in general can include storage in databases, files, Redis, and not just in variables.
That is, all memoization is caching, but not all caching is memoization.
How does Memoization work in Ruby?
In Ruby, memoization is typically done using the ||= operator (or explicitly storing the value in a variable) to keep the result in a variable and return it on subsequent calls.
class User
attr_reader :name
def initialize(name)
@name = name
end
def formatted_name
@formatted_name ||= name.upcase
end
end
user = User.new("Marty")
puts user.formatted_name # Performs computation and stores the value
puts user.formatted_name # Uses the cached value
In this case, @formatted_name ||= name.upcase means:
- If @formatted_name is not set yet (nil or false), it will get the value name.upcase.
- Otherwise, the already stored value is returned.
Note about ||=
The ||= operator works correctly if the value can be nil or false, but if the expected value can be false, then such memoization will not work. For example:
@result ||= false
If @result is false, the expression will compute again.
For reliable memoization, explicit assignment can be used:
@result = some_expensive_operation if @result.nil?
How does Memoization work in Rails?
In Ruby on Rails, memoization is used to optimize database queries and other costly operations. Example of memoization in a model:
class User < ApplicationRecord
def expensive_query
@expensive_query ||= some_heavy_calculation
end
private
def some_heavy_calculation
sleep(2) # Simulating a heavy operation
"Calculation result"
end
end
user = User.first
puts user.expensive_query # Waits 2 seconds
puts user.expensive_query # Gets the cached value
Memoization in before_action in a controller:
class UsersController < ApplicationController
before_action :set_user
def show
render json: { user: @user }
end
private
def set_user
@user ||= User.find(params[:id])
end
end
This helps avoid repeated database queries if the @user method is used multiple times in the action.
What is the difference between memoization and caching?
In short:
Memoization is storing the result within a single running process (e.g., in an instance variable of an object).
Caching is a broader term that can include storing data between processes, in databases, files, Redis, Memcached, etc.
This post doesn't have any additions from the author yet.