LoginSignup
0
2

More than 5 years have passed since last update.

Ruby の Digest(name) にかかるコストを把握してなかった

Posted at

以下の問題に遭遇して以来、ダイジェスト値を計算する際に Digest(:MD5).hexdigest(str) と書く様にしていました。autoload かどうかに関わらず…。

単純に毎回 Digest(name) 関数を実行していると、複数回繰り返し呼ばれる様な場合に著しく時間がかかる事を、最近ようやく把握しました…。

require 'digest/md5'
require 'benchmark'

N = 100_000
nums = 1.upto(N).map(&:to_s)

Benchmark.bm(15) do |x|
  x.report('Digest::MD5') do
    nums.each { |num| Digest::MD5.hexdigest(num) }
  end

  x.report('memoized') do
    digest = Digest(:MD5)
    nums.each { |num| digest.hexdigest(num) }
  end

  x.report('Digest(:MD5)') do
    nums.each { |num| Digest(:MD5).hexdigest(num) }
  end
end

__END__
                      user     system      total        real
Digest::MD5       0.170000   0.010000   0.180000 (  0.182523)
memoized          0.130000   0.000000   0.130000 (  0.132090)
Digest(:MD5)      8.120000   7.750000  15.870000 ( 42.705663)

Digest(name) 関数の実装は以下の通り。

# https://github.com/ruby/ruby/blob/trunk/ext/digest/lib/digest.rb#L96-L109
def Digest(name)
  const = name.to_sym
  Digest::REQUIRE_MUTEX.synchronize {
    # Ignore autoload's because it is void when we have #const_missing
    Digest.const_missing(const)
  }
rescue LoadError
  # Constants do not necessarily rely on digest/*.
  if Digest.const_defined?(const)
    Digest.const_get(const)
  else
    raise
  end
end

require 'digest/md5' してから Digest::MD5.hexdigest(str) を実行すれば良い話だった気がします。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2