Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save secretpray/13d1bb9cfddf576751f4c287468a1714 to your computer and use it in GitHub Desktop.
Save secretpray/13d1bb9cfddf576751f4c287468a1714 to your computer and use it in GitHub Desktop.
How OpenStruct and OrderedOptions Can Kill Performance
require "active_support/ordered_options"
require 'benchmark/ips'
require 'ostruct'

data = { x: 100, y: 200 }

PointStruct = Struct.new(:x, :y)
point_options = ActiveSupport::OrderedOptions.new

class PointClass
  attr_accessor :x, :y
  def initialize(args)
    @x = args.fetch(:x)
    @y = args.fetch(:y)
  end
end

puts "\n\nINITIALIZATION =========="

Benchmark.ips do |x|
  x.report("PointStruct") { PointStruct.new(100, 200) }
  x.report("PointClass") { PointClass.new(data) }
  x.report("Hash") { Hash.new.merge(data) }
  x.report("OpenStruct") { OpenStruct.new(data) }
  x.report("PointOrderedOptions") { point_options.x, point_options.y = 100, 200 }
end

puts "\n\nREAD =========="

point_struct = PointStruct.new(100, 200)
point_class = PointClass.new(data)
point_hash = Hash.new.merge(data)
point_open_struct = OpenStruct.new(data)
point_options.x, point_options.y = 100, 200

Benchmark.ips do |x|
  x.report("PointStruct") { point_struct.x }
  x.report("PointClass") {  point_class.x }
  x.report("Hash") { point_hash.fetch(:x) }
  x.report("OpenStruct") {  point_open_struct.x }
  x.report("PointOrderedOptions") { point_options.x }
end

puts "\n\nWRITE =========="

Benchmark.ips do |x|
  x.report("PointStruct") { point_struct.x = 1 }
  x.report("PointClass") {  point_class.x = 1 }
  x.report("Hash") { point_hash[:x] = 1 }
  x.report("OpenStruct") { point_open_struct.x = 1 }
  x.report("PointOrderedOptions") { point_options.x = 1 }
end

Rusult

INITIALIZATION ==========
Warming up --------------------------------------
         PointStruct   512.212k i/100ms
          PointClass   412.763k i/100ms
                Hash   375.824k i/100ms
          OpenStruct    14.685k i/100ms
 PointOrderedOptions   110.364k i/100ms
Calculating -------------------------------------
         PointStruct      5.264M (± 0.6%) i/s -     26.635M in   5.060086s
          PointClass      4.120M (± 0.8%) i/s -     20.638M in   5.009612s
                Hash      3.763M (± 0.2%) i/s -     19.167M in   5.093829s
          OpenStruct    146.502k (± 1.0%) i/s -    734.250k in   5.012353s
 PointOrderedOptions      1.106M (± 1.3%) i/s -      5.629M in   5.090535s


READ ==========
Warming up --------------------------------------
         PointStruct     1.415M i/100ms
          PointClass     1.419M i/100ms
                Hash     1.234M i/100ms
          OpenStruct   895.468k i/100ms
 PointOrderedOptions   220.455k i/100ms
Calculating -------------------------------------
         PointStruct     14.439M (± 1.0%) i/s -     72.187M in   5.000009s
          PointClass     14.754M (± 3.6%) i/s -     73.790M in   5.008472s
                Hash     12.122M (± 0.5%) i/s -     61.706M in   5.090357s
          OpenStruct      8.947M (± 2.3%) i/s -     44.773M in   5.007375s
 PointOrderedOptions      2.184M (± 0.8%) i/s -     11.023M in   5.048059s


WRITE ==========
Warming up --------------------------------------
         PointStruct     1.083M i/100ms
          PointClass     1.355M i/100ms
                Hash     1.183M i/100ms
          OpenStruct   600.361k i/100ms
 PointOrderedOptions   225.849k i/100ms
Calculating -------------------------------------
         PointStruct     10.956M (± 1.0%) i/s -     55.248M in   5.043431s
          PointClass     13.527M (± 5.6%) i/s -     67.741M in   5.028660s
                Hash     11.891M (± 0.4%) i/s -     60.346M in   5.075060s
          OpenStruct      5.973M (± 1.7%) i/s -     30.018M in   5.027147s
 PointOrderedOptions      2.217M (± 0.8%) i/s -     11.292M in   5.094312s
@secretpray
Copy link
Author

secretpray commented Apr 17, 2023

Sources:
One
Two

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment