fastruby / fast-ruby

:dash: Writing Fast Ruby :heart_eyes: -- Collect Common Ruby idioms.
https://github.com/fastruby/fast-ruby
5.67k stars 376 forks source link

Add comparison from this article #43

Open gogainda opened 9 years ago

gogainda commented 9 years ago

http://blog.honeybadger.io/how-openstruct-and-hashes-can-kill-performance

KostiantynPopovych commented 2 years ago

Hey @gogainda, if you are still interested in this, can you add it please, if you don't mind?

gogainda commented 2 years ago

Hi, sorry, dont have capacity for that right now. Pasting here code which should be adopted for fast-ruby project:

require 'benchmark/ips'
require 'ostruct'

# Enable and start GC before each job run. Disable GC afterwards.
#
# Inspired by https://www.omniref.com/ruby/2.2.1/symbols/Benchmark/bm?#annotation=4095926&line=182
class GCSuite
  def warming(*)
    run_gc
  end

  def running(*)
    run_gc
  end

  def warmup_stats(*)
  end

  def add_report(*)
  end

  private

  def run_gc
    GC.enable
    GC.start
    GC.disable
  end
end

suite = GCSuite.new

data = { x: 100, y: 200 }

PointStruct = Struct.new(:x, :y)

class FakedPointStruct
  attr_accessor :x, :y
  def initialize(x, y)
    @x = x
    @y = y
  end
end

class PointClass
  attr_accessor :x, :y
  def initialize(args)
    @x = args.fetch(:x) # NOTE: Hash#fetch -> performance impact
    @y = args.fetch(:y)
  end
end

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

Benchmark.ips do |x|
  x.config(suite: suite)

  # Create Objects as a reference value
  x.report("Object.new") { Object.new }

  x.report("FakedPointStruct") { FakedPointStruct.new(100, 200) }
  x.report("PointStruct") { PointStruct.new(100, 200) }
  x.report("Hash[]") { Hash[data] }
  x.report("PointClass") { PointClass.new(data) }
  x.report("Hash#merge") { Hash.new.merge(data) }
  x.report("OpenStruct") { OpenStruct.new(data) }
end

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

point_struct = PointStruct.new(100, 200)
point_class = PointClass.new(data)
point_hash = Hash[data]
point_open_struct = OpenStruct.new(data)

Benchmark.ips do |x|
  x.config(suite: suite)

  x.report("PointStruct") { point_struct.x }
  x.report("PointClass") {  point_class.x }
  x.report("Hash#fetch") { point_hash.fetch(:x) }
  x.report("Hash#[]") { point_hash[:x] }
  x.report("OpenStruct") {  point_open_struct.x }
end

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

Benchmark.ips do |x|
  x.config(suite: suite)

  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 }
end