Skip to content

Instantly share code, notes, and snippets.

@elia
Created August 7, 2015 17:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elia/e63d3f3dcf1ac0850483 to your computer and use it in GitHub Desktop.
Save elia/e63d3f3dcf1ac0850483 to your computer and use it in GitHub Desktop.
require 'benchmark/ips'
require 'set'
require 'digest'
# The encouragement:
# https://github.com/elia/sprockets/blob/3-0/let-it-go/lib/sprockets/digest_utils.rb#L37-L44
def digest_class
Digest::SHA256
end
def frozen_digest(obj)
digest = digest_class.new
queue = [obj]
while queue.length > 0
obj = queue.shift
klass = obj.class
if klass == String
digest << obj
elsif klass == Symbol
digest << 'Symbol'.freeze
digest << obj.to_s
elsif klass == Fixnum
digest << 'Fixnum'.freeze
digest << obj.to_s
elsif klass == Bignum
digest << 'Bignum'.freeze
digest << obj.to_s
elsif klass == TrueClass
digest << 'TrueClass'.freeze
elsif klass == FalseClass
digest << 'FalseClass'.freeze
elsif klass == NilClass
digest << 'NilClass'.freeze
elsif klass == Array
digest << 'Array'.freeze
queue.concat(obj)
elsif klass == Hash
digest << 'Hash'.freeze
queue.concat(obj.sort)
elsif klass == Set
digest << 'Set'.freeze
queue.concat(obj.to_a)
elsif klass == Encoding
digest << 'Encoding'.freeze
digest << obj.name
else
raise TypeError, "couldn't digest #{klass}"
end
end
digest.digest
end
def digest(obj)
digest = digest_class.new
queue = [obj]
while queue.length > 0
obj = queue.shift
klass = obj.class
if klass == String
digest << obj
elsif klass == Symbol
digest << 'Symbol'
digest << obj.to_s
elsif klass == Fixnum
digest << 'Fixnum'
digest << obj.to_s
elsif klass == Bignum
digest << 'Bignum'
digest << obj.to_s
elsif klass == TrueClass
digest << 'TrueClass'
elsif klass == FalseClass
digest << 'FalseClass'
elsif klass == NilClass
digest << 'NilClass'
elsif klass == Array
digest << 'Array'
queue.concat(obj)
elsif klass == Hash
digest << 'Hash'
queue.concat(obj.sort)
elsif klass == Set
digest << 'Set'
queue.concat(obj.to_a)
elsif klass == Encoding
digest << 'Encoding'
digest << obj.name
else
raise TypeError, "couldn't digest #{klass}"
end
end
digest.digest
end
GC.disable
Benchmark.ips do |x|
x.config(time: 5, warmup: 2)
objects = [
'asdfasd',
nil,
123,
2983746198476219876492, #Bignum
{a: 123},
[123, 123, 123],
Set.new([345,345,345]),
true,
false,
:asdfasdf,
"asdfasdfa".encoding,
]
x.report('frozen') { objects.each {|o| frozen_digest(o)} }
x.report('plain') { objects.each {|o| digest(o)} }
objects = [nil]*10
x.report('nil-frozen') { objects.each {|o| frozen_digest(o)} }
x.report('nil-plain') { objects.each {|o| digest(o)} }
x.compare!
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment