BlankSlate

いや、そういう声もあるというだけです

メモ

class Base
  attr_reader :id

  def initialize(id)
    @id = id
  end

  @@bots = %w[844196 sasairc hyousikinuko keepoff07]
end

class User < Base
  def bot?
    @@bots.include?(@id)
  end
end

hige = User.new('keepoff07')
hige.bot? #=> true

こんな感じのクラスとインスタンスメソッドがある。

この時、User#bot?メソッドを繰り返し呼ばれるような使い方の場合は、毎回呼び出される度に処理(この場合クラス変数とのマッチング)が走って重い。

これを、

  • 初回呼び出し時に処理結果をインスタンス変数等に格納しておく
  • 2回目以降の呼び出しの際は、処理せず、初回呼び出し時に格納したインスタンス変数の値を返す

ようにすることをメモ化というらしい。User#bot?をメモ化すると多分こんな感じになる。

class NewUser < Base
  def bot?
    # 変数に`?'が使えたらいいんだけどなぁ
    @is_bot ||= @@bots.include?(@id)
  end
end

今回は1億回試行して2倍程度の差だったけど、メモ化するメソッドの処理内容によってはもっと速くなったりする1。1億回も同じインスタンスメソッドを呼び出すことはないので、実際はそんなに速くならないけどね。

require 'benchmark'

old_user = User.new('844196')
new_user = NewUser.new('844196')

N = 100_000_000
Benchmark.bm 10 do |x|
  x.report 'old' do
    N.times { old_user.bot? }
  end

  x.report 'new' do
    N.times { new_user.bot? }
  end
end
                 user     system      total        real
old         18.310000   0.000000  18.310000 ( 18.290078)
new         11.020000   0.000000  11.020000 ( 11.012119)
  1. 設定値保持用クラスへの値取得メソッドをメモ化したら80倍速くなった。

History