Skip to content

Instantly share code, notes, and snippets.

@chrisdavies
Created June 23, 2016 13:41
Show Gist options
  • Save chrisdavies/fb1ea90afdb226e28b6d7b984acbc727 to your computer and use it in GitHub Desktop.
Save chrisdavies/fb1ea90afdb226e28b6d7b984acbc727 to your computer and use it in GitHub Desktop.
A perf test of Ruby's OpenStruct vs a few other options
# OpenStruct is slow. But if you need/want similar functionality,
# you can achieve it with really good perf results. See the impl
# of NotificationEvent below.
#
# Benchmark results from my Macbook (2.6 GHz Intel Core i5)
#
# Rehearsal -----------------------------------------------------
# Literal 1.060000 0.020000 1.080000 ( 1.080056)
# NotificationEvent 1.350000 0.000000 1.350000 ( 1.367066)
# OpenStruct 11.500000 0.110000 11.610000 ( 11.646464)
# ------------------------------------------- total: 14.040000sec
#
# user system total real
# Literal 1.000000 0.010000 1.010000 ( 1.015018)
# NotificationEvent 1.380000 0.010000 1.390000 ( 1.395112)
# OpenStruct 11.980000 0.300000 12.280000 ( 12.798998)
require 'benchmark'
require 'ostruct'
class Literal
attr_reader :event_name, :user, :age
def initialize(event_name, hash)
@event_name = event_name
@user = hash[:user]
@age = hash[:age]
end
end
# NotificationEvent is essentially a struct, no methods, just read-only
# properties describing the event.
class NotificationEvent
attr_reader :event_name
def initialize(event_name, hash)
@event_name = event_name
@hash = hash
end
# Exposes hash keys as object properties for easier access and better duck-typing
def method_missing(mid, *args)
if args.length > 0
raise "Property #{mid} does not accept arguments #{args}"
end
@hash.fetch(mid)
end
end
def test_struct(count)
x = 0
for i in 0..count
evt = yield
x += evt.age + evt.user.length
end
return x
end
def literal_test(count)
test_struct(count) { Literal.new('foo', user: 'Chris', age: 23) }
end
def notify_test(count)
test_struct(count) { NotificationEvent.new('foo', user: 'Chris', age: 23) }
end
def open_test(count)
test_struct(count) { OpenStruct.new(user: 'Chris', age: 23) }
end
Benchmark.bmbm do |x|
count = 1000000
x.report('Literal') { literal_test(count) }
x.report('NotificationEvent') { notify_test(count) }
x.report('OpenStruct') { open_test(count) }
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment