rom-rb / rom

Data mapping and persistence toolkit for Ruby
https://rom-rb.org
MIT License
2.09k stars 161 forks source link

Move modules from rom-support to rom #365

Closed flash-gordon closed 7 years ago

flash-gordon commented 7 years ago

Still on the list

flash-gordon commented 7 years ago

@solnic any comments?

flash-gordon commented 7 years ago

I won't forget to update the changelog this time, I promise

solnic commented 7 years ago

❤️ 💚 💜 💙 💛

solnic commented 7 years ago

ROM::Options (I guess we can use dry-initializer, I'll give it a try)

In order to do that we must verify performance. Options are used literally everywhere and rom, as you know, creates new objects instead of changing them, so initializers must be fast :)

flash-gordon commented 7 years ago

Yeah, I checked that once, it was faster than ROM::Options. Anyway I'll benchmark that again

solnic commented 7 years ago

@flash-gordon if you checked that already then it's fine :) unless you don't feel strong enough about it

flash-gordon commented 7 years ago

Well, it was a while ago, things have changed. Now dry-initializer is slower, but that's because of ... dry-types. This is only true when we check types, otherwise dry-initializer 2x-3x times faster than ROM

bundle exec ruby ./benchmarks/with_types.rb
Benchmark for instantiation with type constraints
Warming up --------------------------------------
          plain Ruby    51.900k i/100ms
     dry-initializer     8.668k i/100ms
              virtus    11.401k i/100ms
     fast_attributes    35.387k i/100ms
                 rom    11.148k i/100ms
Calculating -------------------------------------
          plain Ruby    592.015k (± 5.9%) i/s -      8.875M in  15.042768s
     dry-initializer     86.834k (± 4.4%) i/s -      1.300M in  15.002131s
              virtus    113.951k (± 5.2%) i/s -      1.710M in  15.051657s
     fast_attributes    406.862k (± 4.9%) i/s -      6.122M in  15.084655s
                 rom    117.224k (± 5.2%) i/s -      1.761M in  15.068541s

Comparison:
          plain Ruby:   592015.3 i/s
     fast_attributes:   406861.9 i/s - 1.46x  slower
                 rom:   117224.3 i/s - 5.05x  slower
              virtus:   113951.2 i/s - 5.20x  slower
     dry-initializer:    86834.4 i/s - 6.82x  slower
Bundler.require(:benchmarks)

class PlainRubyTest
  attr_reader :foo, :bar

  def initialize(foo:, bar:)
    @foo = foo
    @bar = bar
    fail TypeError unless String === @foo
    fail TypeError unless String === @bar
  end
end

require "dry-initializer"
require 'dry-types'
# require "dry/initializer/types"
class DryTest
  extend Dry::Initializer::Mixin
  # extend Dry::Initializer::Types

  option :foo, type: Dry::Types['strict.string']
  option :bar, type: Dry::Types['strict.string']
end

require "virtus"
class VirtusTest
  include Virtus.model

  attribute :foo, String
  attribute :bar, String
end

require "fast_attributes"
class FastAttributesTest
  extend FastAttributes

  define_attributes initialize: true do
    attribute :foo, String
    attribute :bar, String
  end
end

require 'rom/support/options'
class ROMTest
  include ROM::Options

  option :foo, reader: true, type: String
  option :bar, reader: true, type: String
end

puts "Benchmark for instantiation with type constraints"

Benchmark.ips do |x|
  x.config time: 15, warmup: 10

  x.report("plain Ruby") do
    PlainRubyTest.new foo: "FOO", bar: "BAR"
  end

  x.report("dry-initializer") do
    DryTest.new foo: "FOO", bar: "BAR"
  end

  x.report("virtus") do
    VirtusTest.new foo: "FOO", bar: "BAR"
  end

  x.report("fast_attributes") do
    FastAttributesTest.new foo: "FOO", bar: "BAR"
  end

  x.report("rom") do
    ROMTest.new foo: "FOO", bar: "BAR"
  end

  x.compare!
end
solnic commented 7 years ago

Well, it was a while ago, things have changed. Now dry-initializer is slower, but that's because of ... dry-types. This is only true when we check types, otherwise dry-initializer 2x-3x times faster than ROM

This is fine, and even if it turns out to be a problem we can tweak it.