Created
June 23, 2016 13:41
-
-
Save chrisdavies/fb1ea90afdb226e28b6d7b984acbc727 to your computer and use it in GitHub Desktop.
A perf test of Ruby's OpenStruct vs a few other options
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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