Skip to content

Instantly share code, notes, and snippets.

@pcreux
Last active November 6, 2015 18:59
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 pcreux/275428d19341b1964f55 to your computer and use it in GitHub Desktop.
Save pcreux/275428d19341b1964f55 to your computer and use it in GitHub Desktop.
Are data objects slow?
require 'time'
require 'virtus'
require 'benchmark/ips'
PARAMS = {
id: "123",
title: "Hello",
content: "Lorem ipsum" * 100,
created_at: Time.now.to_s,
updated_at: Time.now.to_s
}
class ThePORO
def initialize(id:, title:, content:, created_at:, updated_at:)
@id = id.to_i
@title = title
@content = content
@created_at = Time.parse(created_at)
@updated_at = Time.parse(updated_at)
end
end
class TheStruct < Struct.new(:id, :title, :content, :created_at, :updated_at)
end
class TheVirtus
include Virtus.model
attribute :id, Integer
attribute :title, String
attribute :content, String
attribute :created_at, Time
attribute :updated_at, Time
end
Benchmark.ips do |x|
x.report "Dup and update" do
params = PARAMS.clone
params[:id] = PARAMS[:id].to_i
params[:created_at] = Time.parse PARAMS[:created_at]
params[:updated_at] = Time.parse PARAMS[:updated_at]
end
x.report "PORO" do
ThePORO.new(
id: PARAMS.fetch(:id),
title: PARAMS.fetch(:title),
content: PARAMS.fetch(:content),
created_at: PARAMS.fetch(:created_at),
updated_at: PARAMS.fetch(:updated_at),
)
end
x.report "Struct" do
TheStruct.new(
PARAMS.fetch(:id).to_i,
PARAMS.fetch(:title),
PARAMS.fetch(:content),
Time.parse(PARAMS.fetch(:created_at)),
Time.parse(PARAMS.fetch(:updated_at))
)
end
x.report "Virtus" do
TheVirtus.new(PARAMS)
end
end
require 'time'
require 'virtus'
require 'benchmark/ips'
PARAMS = {
id: "123",
title: "Hello",
content: "Lorem ipsum" * 100,
created_at: Time.now,
updated_at: Time.now,
}
class ThePORO
def initialize(id:, title:, content:, created_at:, updated_at:)
@id = id.to_i
@title = title
@content = content
@created_at = created_at
@updated_at = updated_at
end
end
class TheStruct < Struct.new(:id, :title, :content, :created_at, :updated_at)
end
class TheVirtus
include Virtus.model
attribute :id, Integer
attribute :title, String
attribute :content, String
attribute :created_at, Time
attribute :updated_at, Time
end
Benchmark.ips do |x|
x.report "Dup and update" do
params = PARAMS.clone
params[:id] = PARAMS[:id].to_i
params[:created_at] = PARAMS[:created_at]
params[:updated_at] = PARAMS[:updated_at]
end
x.report "PORO" do
ThePORO.new(
id: PARAMS.fetch(:id),
title: PARAMS.fetch(:title),
content: PARAMS.fetch(:content),
created_at: PARAMS.fetch(:created_at),
updated_at: PARAMS.fetch(:updated_at),
)
end
x.report "Struct" do
TheStruct.new(
PARAMS.fetch(:id).to_i,
PARAMS.fetch(:title),
PARAMS.fetch(:content),
PARAMS.fetch(:created_at),
PARAMS.fetch(:updated_at)
)
end
x.report "Virtus" do
TheVirtus.new(PARAMS)
end
end

Are Data Objects Slow

TL;DR

Virtus is 20+ times slower to instantiate an object from a hash than using a Plain Old Ruby Object or Struct.

If this process involves parsing timestamps into Time objects Virtus is then only 2 times slower.

We are talking 0.00001 ms vs 0.000005 ms to instantiate an object here. In the context of handling an http request in a rails app, I believe that the performance impact is non existent.

Results

With time parsing

Calculating ------------------------------------- Dup and update 1.728k i/100ms PORO 1.695k i/100ms Struct 1.760k i/100ms Virtus 928.000 i/100ms

  Dup and update     18.171k (±15.5%) i/s -     89.856k
            PORO     17.772k (±12.4%) i/s -     88.140k
          Struct     18.479k (±13.8%) i/s -     91.520k
          Virtus      9.254k (±11.5%) i/s -     46.400k

No time parsing

Calculating ------------------------------------- Dup and update 44.825k i/100ms PORO 36.665k i/100ms Struct 72.831k i/100ms Virtus 2.596k i/100ms

  Dup and update    686.871k (±15.7%) i/s -      3.362M
            PORO    427.578k (±26.1%) i/s -      1.980M
          Struct      1.222M (±20.2%) i/s -      5.826M
          Virtus     20.415k (±26.8%) i/s -     90.860k
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment