Skip to content

Instantly share code, notes, and snippets.

@mrinterweb
Last active June 1, 2024 23:56
Show Gist options
  • Save mrinterweb/e063ffc4bcfc9cfb05302c50e479ecd7 to your computer and use it in GitHub Desktop.
Save mrinterweb/e063ffc4bcfc9cfb05302c50e479ecd7 to your computer and use it in GitHub Desktop.
Ruby benchmark OpenStruct vs Hash vs Class vs Struct vs Data
That is 266 microseconds vs 2 microseconds. When compared OpenStuct is a lot slower, but when used infrequently, microseconds are minimal.
Just don't use OpenStruct where it will be instantiated a lot or in a performance critical spot in your app.
require 'ostruct'
require 'benchmark'
require 'benchmark/ips'
if defined?(RubyVM::YJIT)
RubyVM::YJIT.enable
puts "YJIT is enabled"
end
data = {:name => "John", :age => 28}
class Person
attr_reader :name, :age
def initialize(data)
@name = data[:name]
@age = data[:age]
end
end
Person2 = Struct.new(:name, :age)
Person3 = Data.define(:name, :age)
puts "How many total iterations can this run in 5 seconds?"
Benchmark.ips do |x|
x.report("OpenStruct") do
OpenStruct.new(data)
end
x.report("Hash") do
{ **data }
end
x.report("Class instantiation") do
Person.new(data)
end
x.report("Struct instantiation") do
Person2.new(data[:name], data[:aget])
end
x.report("Data instantiation") do
Person3.new(data[:name], data[:age])
end
x.compare!
end
puts "-" * 50
puts "\n"
puts "Now only itterating 10 times"
puts "The point of this is to show the difference in speed when only running a few times."
puts "Yes OpenStruct is a lot slower, but it depends how it is used."
puts "If you only use OpenStruct a few times, the speed difference is hardly noticable."
puts "-" * 50
puts "\n"
Benchmark.bm(10) do |x|
x.report("OpenStruct") do
OpenStruct.new(data)
end
x.report("Hash") do
{ **data }
end
x.report("Class instantiation") do
Person.new(data)
end
x.report("Struct instantiation") do
Person2.new(data[:name], data[:age])
end
x.report("Data instantiation") do
Person3.new(data[:name], data[:age])
end
end
YJIT is enabled
How many total iterations can this run in 5 seconds?
ruby 3.3.1 (2024-04-23 revision c56cd86388) +YJIT [arm64-darwin23]
Warming up --------------------------------------
OpenStruct 22.247k i/100ms
Hash 804.918k i/100ms
Class instantiation 761.548k i/100ms
Struct instantiation 707.328k i/100ms
Data instantiation 384.114k i/100ms
Calculating -------------------------------------
OpenStruct 218.212k (± 0.7%) i/s - 1.112M in 5.097830s
Hash 9.618M (± 0.3%) i/s - 48.295M in 5.021430s
Class instantiation 8.906M (± 1.7%) i/s - 44.931M in 5.046682s
Struct instantiation 8.311M (± 1.0%) i/s - 41.732M in 5.021752s
Data instantiation 4.211M (± 0.8%) i/s - 21.126M in 5.017157s
Comparison:
Hash: 9617902.1 i/s
Class instantiation: 8906070.6 i/s - 1.08x slower
Struct instantiation: 8311149.8 i/s - 1.16x slower
Data instantiation: 4211094.7 i/s - 2.28x slower
OpenStruct: 218211.6 i/s - 44.08x slower
--------------------------------------------------
Now only itterating 10 times
The point of this is to show the difference in speed when only running a few times.
Yes OpenStruct is a lot slower, but it depends how it is used.
If you only use OpenStruct a few times, the speed difference is hardly noticable.
--------------------------------------------------
user system total real
OpenStruct 0.000022 0.000001 0.000023 ( 0.000019)
Hash 0.000002 0.000000 0.000002 ( 0.000002)
Class instantiation 0.000002 0.000001 0.000003 ( 0.000002)
Struct instantiation 0.000002 0.000000 0.000002 ( 0.000002)
Data instantiation 0.000002 0.000001 0.000003 ( 0.000002)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment