Skip to content

Instantly share code, notes, and snippets.

@IvanShamatov
Last active October 24, 2023 11:40
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save IvanShamatov/94e78ca52f04f20c6085651345dbdfda to your computer and use it in GitHub Desktop.
Save IvanShamatov/94e78ca52f04f20c6085651345dbdfda to your computer and use it in GitHub Desktop.
require 'benchmark'
require 'benchmark/memory'
require 'dry-struct'
require 'dry-initializer'
require 'virtus'
require 'shallow_attributes'
require 'active_data'
require 'active_model'
require 'benchmark/ips'
DataResult = Data.define(
:commission,
:who_is_on_duty,
:charged,
:received,
:service_fee,
:executed_rate,
:provided_rate,
:margin
)
StructResult = Struct.new(
:commission,
:who_is_on_duty,
:charged,
:received,
:service_fee,
:executed_rate,
:provided_rate,
:margin
)
class DryInitializerResult
extend Dry::Initializer
option :commission, optional: true
option :who_is_on_duty, optional: true
option :charged, optional: true
option :received, optional: true
option :service_fee, optional: true
option :executed_rate, optional: true
option :provided_rate, optional: true
option :margin, optional: true
end
module Types
include Dry.Types()
end
class DryStructValueResult < Dry::Struct::Value
attribute :commission, Types::Strict::Float
attribute :who_is_on_duty, Types::Strict::Bool
attribute :charged, Types::Strict::Float
attribute :received, Types::Strict::Float
attribute :service_fee, Types::Strict::Float
attribute :executed_rate, Types::Strict::Float
attribute :provided_rate, Types::Strict::Float
attribute :margin, Types::Strict::Float
end
class DryStructResult < Dry::Struct
attribute :commission, Types::Strict::Float
attribute :who_is_on_duty, Types::Strict::Bool
attribute :charged, Types::Strict::Float
attribute :received, Types::Strict::Float
attribute :service_fee, Types::Strict::Float
attribute :executed_rate, Types::Strict::Float
attribute :provided_rate, Types::Strict::Float
attribute :margin, Types::Strict::Float
end
class ShallowAttributesWithDryTypesResult
include ShallowAttributes
attribute :commission, Types::Strict::Float
attribute :who_is_on_duty, Types::Strict::Bool
attribute :charged, Types::Strict::Float
attribute :received, Types::Strict::Float
attribute :service_fee, Types::Strict::Float
attribute :executed_rate, Types::Strict::Float
attribute :provided_rate, Types::Strict::Float
attribute :margin, Types::Strict::Float
end
class ShallowAttributesTypesResult
include ShallowAttributes
attribute :commission, Float
attribute :who_is_on_duty, 'Boolean'
attribute :charged, Float
attribute :received, Float
attribute :service_fee, Float
attribute :executed_rate, Float
attribute :provided_rate, Float
attribute :margin, Float
end
class VirtusResult
include Virtus.model
attribute :commission, Float
attribute :who_is_on_duty, Boolean
attribute :charged, Float
attribute :received, Float
attribute :service_fee, Float
attribute :executed_rate, Float
attribute :provided_rate, Float
attribute :margin, Float
end
class ActiveDataResult
include ActiveData::Model
attribute :commission, Float
attribute :who_is_on_duty, Boolean
attribute :charged, Float
attribute :received, Float
attribute :service_fee, Float
attribute :executed_rate, Float
attribute :provided_rate, Float
attribute :margin, Float
end
class ActiveModelResult
include ActiveModel::Model
attr_accessor :commission,
:who_is_on_duty,
:charged,
:received,
:service_fee,
:executed_rate,
:provided_rate,
:margin
end
values = {
commission: 0.02,
who_is_on_duty: true,
charged: 2355.234,
received: 235.234,
service_fee: 23.34,
executed_rate: 123000.122,
provided_rate: 122000.003,
margin: 120.3
}.freeze
n = 50000
Benchmark.memory do |x|
x.report('VirtusResult') { n.times { VirtusResult.new(values) } }
x.report('DryStructResult') { n.times { DryStructResult.new(values) } }
x.report('DryStructValueResult') { n.times { DryStructValueResult.new(values) } }
x.report('DataResult') { n.times { DataResult.new(**values) } }
x.report('StructResult') { n.times { StructResult.new(values) } }
x.report('DryInitializerResult') { n.times { DryInitializerResult.new(values) } }
x.report('ShAttsResult') { n.times { ShallowAttributesTypesResult.new(values) } }
x.report('ShAttsDryTypesResult') { n.times { ShallowAttributesWithDryTypesResult.new(values) } }
x.report('ActiveDataResult') { n.times { ActiveDataResult.new(values) } }
x.report('ActiveModelResult') { n.times { ActiveModelResult.new(values) } }
x.compare!
end
Benchmark.ips do |x|
x.report('DataResult') { DataResult.new(**values) }
x.report('StructResult') { StructResult.new(values) }
x.report('DryInitializerResult') { DryInitializerResult.new(values) }
x.report('DryStructResult') { DryStructResult.new(values) }
x.report('DryStructValueResult') { DryStructValueResult.new(values) }
x.report('VirtusResult') { VirtusResult.new(values) }
x.report('ShAttrsResult') { ShallowAttributesTypesResult.new(values) }
x.report('ShAttrsDryTypesResult') { ShallowAttributesWithDryTypesResult.new(values) }
x.report('ActiveDataResult') { ActiveDataResult.new(values) }
x.report('ActiveModelResult') { ActiveModelResult.new(values) }
x.compare!
end
# MEMORY BENCHMARK
#
# Calculating -------------------------------------
# VirtusResult 38.409M memsize ( 1.536k retained)
# 700.113k objects ( 11.000 retained)
# 50.000 strings ( 2.000 retained)
# DryStructResult 10.573M memsize ( 64.897k retained)
# 100.745k objects ( 214.000 retained)
# 50.000 strings ( 50.000 retained)
# DryStructValueResult 66.805M memsize ( 1.208k retained)
# 400.097k objects ( 17.000 retained)
# 23.000 strings ( 7.000 retained)
# DataResult 13.600M memsize ( 0.000 retained)
# 100.000k objects ( 0.000 retained)
# 0.000 strings ( 0.000 retained)
# StructResult 5.200M memsize ( 0.000 retained)
# 50.000k objects ( 0.000 retained)
# 0.000 strings ( 0.000 retained)
# DryInitializerResult 10.000M memsize ( 40.000 retained)
# 200.000k objects ( 1.000 retained)
# 0.000 strings ( 0.000 retained)
# ShAttsResult 36.400M memsize ( 248.000 retained)
# 600.002k objects ( 3.000 retained)
# 8.000 strings ( 1.000 retained)
# ShAttsDryTypesResult 32.400M memsize ( 208.000 retained)
# 500.000k objects ( 2.000 retained)
# 8.000 strings ( 1.000 retained)
# ActiveDataResult 231.200M memsize ( 1.040k retained)
# 4.900M objects ( 14.000 retained)
# 20.000 strings ( 2.000 retained)
# ActiveModelResult 20.000M memsize ( 256.000 retained)
# 450.000k objects ( 3.000 retained)
# 8.000 strings ( 1.000 retained)
# Comparison:
# StructResult: 5200000 allocated
# DryInitializerResult: 10000056 allocated - 1.92x more
# DryStructResult: 10572665 allocated - 2.03x more
# DataResult: 13600000 allocated - 2.62x more
# ActiveModelResult: 20000056 allocated - 3.85x more
# ShAttsDryTypesResult: 32399976 allocated - 6.23x more
# ShAttsResult: 36400360 allocated - 7.00x more
# VirtusResult: 38409336 allocated - 7.39x more
# DryStructValueResult: 66805240 allocated - 12.85x more
# ActiveDataResult: 231200360 allocated - 44.46x more
# IPS BENCHMARK
#
# Warming up --------------------------------------
# DataResult 174.462k i/100ms
# StructResult 389.491k i/100ms
# DryInitializerResult 87.224k i/100ms
# DryStructResult 29.820k i/100ms
# DryStructValueResult 7.197k i/100ms
# VirtusResult 7.080k i/100ms
# ShAttrsResult 15.210k i/100ms
# ShAttrsDryTypesResult
# 12.171k i/100ms
# ActiveDataResult 2.859k i/100ms
# ActiveModelResult 28.380k i/100ms
# Calculating -------------------------------------
# DataResult 1.636M (± 2.6%) i/s - 8.200M in 5.015057s
# StructResult 3.603M (± 2.7%) i/s - 18.306M in 5.084799s
# DryInitializerResult 847.515k (± 2.6%) i/s - 4.274M in 5.046375s
# DryStructResult 294.959k (± 3.0%) i/s - 1.491M in 5.059662s
# DryStructValueResult 70.253k (± 3.1%) i/s - 352.653k in 5.024650s
# VirtusResult 69.636k (± 3.2%) i/s - 354.000k in 5.088752s
# ShAttrsResult 155.235k (± 0.7%) i/s - 790.920k in 5.095200s
# ShAttrsDryTypesResult
# 126.171k (± 3.1%) i/s - 632.892k in 5.020983s
# ActiveDataResult 28.567k (± 2.4%) i/s - 142.950k in 5.007077s
# ActiveModelResult 289.265k (± 3.1%) i/s - 1.447M in 5.008408s
# Comparison:
# StructResult: 3602761.9 i/s
# DataResult: 1636110.3 i/s - 2.20x slower
# DryInitializerResult: 847514.6 i/s - 4.25x slower
# DryStructResult: 294958.5 i/s - 12.21x slower
# ActiveModelResult: 289264.7 i/s - 12.45x slower
# ShAttrsResult: 155235.5 i/s - 23.21x slower
# ShAttrsDryTypesResult: 126170.8 i/s - 28.55x slower
# DryStructValueResult: 70253.1 i/s - 51.28x slower
# VirtusResult: 69636.1 i/s - 51.74x slower
# ActiveDataResult: 28567.0 i/s - 126.12x slower
@flash-gordon
Copy link

Calculating -------------------------------------
        VirtusResult    60.811M memsize (   832.000  retained)
                         1.100M objects (     5.000  retained)
                        50.000  strings (     0.000  retained)
     DryStructResult    17.600M memsize (     0.000  retained)
                       200.000k objects (     0.000  retained)
                         2.000  strings (     0.000  retained)
DryStructValueResult    72.004M memsize (     0.000  retained)
                       450.082k objects (     0.000  retained)
                        31.000  strings (     0.000  retained)
        StructResult     5.200M memsize (     0.000  retained)
                        50.000k objects (     0.000  retained)
                         0.000  strings (     0.000  retained)
DryInitializerResult    32.400M memsize (     0.000  retained)
                       250.000k objects (     0.000  retained)
                         0.000  strings (     0.000  retained)
        ShAttsResult    65.600M memsize (   232.000  retained)
                         1.050M objects (     1.000  retained)
                        17.000  strings (     0.000  retained)
ShAttsDryTypesResult    50.000M memsize (     0.000  retained)
                       900.000k objects (     0.000  retained)
                        16.000  strings (     0.000  retained)
    ActiveDataResult   327.201M memsize (     0.000  retained)
                         5.700M objects (     0.000  retained)
                        26.000  strings (     0.000  retained)
   ActiveModelResult    48.800M memsize (     0.000  retained)
                       900.000k objects (     0.000  retained)
                        16.000  strings (     0.000  retained)

Comparison:
        StructResult:    5200000 allocated
     DryStructResult:   17600000 allocated - 3.38x more
DryInitializerResult:   32400016 allocated - 6.23x more
   ActiveModelResult:   48800016 allocated - 9.38x more
ShAttsDryTypesResult:   50000016 allocated - 9.62x more
        VirtusResult:   60810952 allocated - 11.69x more
        ShAttsResult:   65600248 allocated - 12.62x more
DryStructValueResult:   72004080 allocated - 13.85x more
    ActiveDataResult:  327200592 allocated - 62.92x more
Warming up --------------------------------------
        StructResult   197.460k i/100ms
DryInitializerResult    64.342k i/100ms
     DryStructResult    21.408k i/100ms
DryStructValueResult     5.744k i/100ms
        VirtusResult     4.765k i/100ms
       ShAttrsResult    11.660k i/100ms
ShAttrsDryTypesResult
                         9.758k i/100ms
    ActiveDataResult     3.075k i/100ms
   ActiveModelResult    20.676k i/100ms
Calculating -------------------------------------
        StructResult      5.599M (±10.6%) i/s -     27.842M in   5.031264s
DryInitializerResult    817.140k (± 9.7%) i/s -      4.054M in   5.007782s
     DryStructResult    246.100k (± 5.2%) i/s -      1.242M in   5.061974s
DryStructValueResult     57.721k (± 9.2%) i/s -    287.200k in   5.026143s
        VirtusResult     50.622k (± 7.0%) i/s -    252.545k in   5.016287s
       ShAttrsResult    120.730k (± 9.6%) i/s -    606.320k in   5.075353s
ShAttrsDryTypesResult
                         99.778k (± 6.3%) i/s -    497.658k in   5.008306s
    ActiveDataResult     28.857k (± 9.5%) i/s -    144.525k in   5.056924s
   ActiveModelResult    218.712k (± 6.3%) i/s -      1.096M in   5.033579s

Comparison:
        StructResult:  5599180.2 i/s
DryInitializerResult:   817139.9 i/s - 6.85x  slower
     DryStructResult:   246099.7 i/s - 22.75x  slower
   ActiveModelResult:   218711.6 i/s - 25.60x  slower
       ShAttrsResult:   120730.1 i/s - 46.38x  slower
ShAttrsDryTypesResult:    99778.1 i/s - 56.12x  slower
DryStructValueResult:    57721.5 i/s - 97.00x  slower
        VirtusResult:    50621.8 i/s - 110.61x  slower
    ActiveDataResult:    28857.2 i/s - 194.03x  slower

@IvanShamatov
Copy link
Author

Ruby's 3.2 Data added to the benchmark. Benchmarks updated today

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