Skip to content

Instantly share code, notes, and snippets.

@holysugar
Last active December 20, 2018 09:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save holysugar/7843d647ac3ee03181eda1e136fab14e to your computer and use it in GitHub Desktop.
Save holysugar/7843d647ac3ee03181eda1e136fab14e to your computer and use it in GitHub Desktop.
雑ベンチ
#!/usr/bin/env ruby
require 'benchmark'
require 'json'
require 'securerandom'
require 'objspace'
require 'active_model'
require 'hashie'
require 'dry-struct'
def columns
[
:id,
:name,
:param1,
:param2,
:param3,
:param4,
:param5,
]
end
def generate(size = 1000)
chars = [*("a".."z"),*("A".."Z"), *("0".."9")]
Array.new(size) { |i|
[
SecureRandom.uuid,
Array.new(10) { chars.sample }.join,
rand(1000),
rand(1000),
rand(1000),
rand(1000),
rand(1000),
]
}
end
def hash_array(data)
data.map do |c|
columns.zip(c).to_h
end
end
MyStruct = Struct.new(*columns, keyword_init: true)
def struct(data)
data.map do |c|
MyStruct.new(**columns.zip(c).to_h)
end
end
MyStructWithValidation = Struct.new(*columns, keyword_init: true)
class MyStructWithValidation
include ActiveModel::Validations
validates :id, presence: true
validates :name, presence: { strict: true}
validates :param1, numericality: { strict: true}
validates :param2, numericality: { strict: true}
validates :param3, numericality: { strict: true}
validates :param4, numericality: { strict: true}
validates :param5, numericality: { strict: true}
end
def structv(data)
data.map do |c|
MyStructWithValidation.new(**columns.zip(c).to_h).tap(&:valid?)
end
end
class MyModel
include ActiveModel::Model
include ActiveModel::Attributes
attribute :id, :string
attribute :name, :string
(1..5).each do |i|
attribute :"param#{i}", :integer
end
end
def am(data)
data.map do |c|
MyModel.new(**columns.zip(c).to_h)
end
end
class MyDash < Hashie::Dash
columns.each do |i|
property i
end
end
def hashie(data)
data.map do |c|
MyDash.new(**columns.zip(c).to_h)
end
end
module Types
include Dry::Types.module
end
class MyDry < Dry::Struct
attribute :id, Types::Strict::String
attribute :name, Types::Strict::String
(1..5).each do |i|
attribute :"param#{i}", Types::Strict::Integer
end
end
def dry(data)
data.map do |c|
MyDry.new(**columns.zip(c).to_h)
end
end
def memsize_of_all_reachable_objects_from(obj, exclude_class = Module)
objs = {}
queue = [obj]
while obj = queue.pop
next if objs[obj.object_id]
next unless reachable_objects = ObjectSpace.reachable_objects_from(obj)
reachable_objects.each{|o|
case o
when ObjectSpace::InternalObjectWrapper
next if objs[o.internal_object_id]
else
next if objs[o.object_id]
end
queue.push o if !exclude_class || !o.kind_of?(exclude_class)
}
objs[obj.respond_to?(:internal_object_id) ? obj.internal_object_id : obj.object_id] = obj
end
objs.inject(0){|r, (_, o)| r += ObjectSpace.memsize_of(o)}
end
def comma(i)
i.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/){|d| "#{d}," }
end
n = 10000
all = generate(n)
result = {}
Benchmark.bmbm(10) do |x|
x.report("hash") { result[:hash] = hash_array(all) }
x.report("struct") { result[:struct] = struct(all) }
x.report("structv") { result[:structv] = structv(all) }
x.report("am") { result[:am] = am(all) }
x.report("hashie") { result[:hashie] = hashie(all) }
x.report("dry") { result[:dry] = dry(all) }
end
#puts
#result.each{|k,v| p v.first }
puts
puts '----> mem'
result.each do |key, obj|
puts "%10s %10s" % [key, comma(memsize_of_all_reachable_objects_from(obj))]
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment