Skip to content

Instantly share code, notes, and snippets.

@antonvolkoff
Created July 19, 2020 13:27
Show Gist options
  • Save antonvolkoff/a99f041b8fc7f654de97e0901008bd44 to your computer and use it in GitHub Desktop.
Save antonvolkoff/a99f041b8fc7f654de97e0901008bd44 to your computer and use it in GitHub Desktop.

Hey, let’s talk about memoization.

I would like to address one of our coding habits. I notice that we have a tendency to overuse memoization. I would like to point out that memoization is a double edge sword and does not always yield expected results.

Here is an example. I pulled it from recent code I saw:

require 'benchmark'
require 'active_support/all'
EDUCATION_DURATION_ESTIMATE = 10.years
DEFAULT_STUDY_DEBT_DURATION = 15.years
def start_date_1
  @start_date ||= (Date.new(2000, 01, 01) + EDUCATION_DURATION_ESTIMATE).to_datetime
end
def end_date_1
  (start_date_1 + DEFAULT_STUDY_DEBT_DURATION).to_datetime
end
def start_date_2
  (Date.new(2000, 01, 01) + EDUCATION_DURATION_ESTIMATE).to_datetime
end
def end_date_2
  (start_date_2 + DEFAULT_STUDY_DEBT_DURATION).to_datetime
end
Benchmark.bm(20) do |x|
  x.report('with memoizing:') do
    start_date_1
    start_date_1
    end_date_1
  end
  x.report('without memoizing:') do
    start_date_2
    start_date_2
    end_date_2
  end
end

Code above executes two scenarios: With memoization Without memoization

Results:
                           user     system      total        real
with memoizing:        0.000098   0.000023   0.000121 (  0.000124)
without memoizing:     0.000038   0.000000   0.000038 (  0.000038)
As you can see code without memoization is two times faster.

Why is it slower?

One of the most expensive operations for your computer is memory allocation. That is why you have loading screens in games and why you want to allocate most of your memory in constructor(initialiser).

When to use memoization?

To cache operations that require IO (database, http, files) To save computation that required

In the example above it takes a while when memoization wins. With trial and error I landed at 29-30 iterations when @start_date variable paid off.

Benchmark.bm(20) do |x|
  x.report('with memoizing:') do
    start_date_1
    30.times { start_date_1 }
    end_date_1
  end
  x.report('without memoizing:') do
    start_date_2
    30.times { start_date_2 }
    end_date_2
  end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment