Skip to content

Instantly share code, notes, and snippets.

@pushcx
Forked from solnic/anima_vs_virtus.rb
Last active August 29, 2015 14:25
Show Gist options
  • Select an option

  • Save pushcx/b5ce6236c0020a4ce3aa to your computer and use it in GitHub Desktop.

Select an option

Save pushcx/b5ce6236c0020a4ce3aa to your computer and use it in GitHub Desktop.

Revisions

  1. pushcx revised this gist Jul 16, 2015. 4 changed files with 120 additions and 6 deletions.
    9 changes: 9 additions & 0 deletions Gemfile
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,9 @@
    source 'https://rubygems.org'

    gem 'activerecord'
    gem 'anima'
    gem 'sqlite3'
    gem 'transproc'
    gem 'virtus'

    gem 'benchmark-ips'
    63 changes: 63 additions & 0 deletions Gemfile.lock
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,63 @@
    GEM
    remote: https://rubygems.org/
    specs:
    abstract_type (0.0.7)
    activemodel (4.2.3)
    activesupport (= 4.2.3)
    builder (~> 3.1)
    activerecord (4.2.3)
    activemodel (= 4.2.3)
    activesupport (= 4.2.3)
    arel (~> 6.0)
    activesupport (4.2.3)
    i18n (~> 0.7)
    json (~> 1.7, >= 1.7.7)
    minitest (~> 5.1)
    thread_safe (~> 0.3, >= 0.3.4)
    tzinfo (~> 1.1)
    adamantium (0.2.0)
    ice_nine (~> 0.11.0)
    memoizable (~> 0.4.0)
    anima (0.2.0)
    abstract_type (~> 0.0.7)
    adamantium (~> 0.1)
    equalizer (~> 0.0.8)
    arel (6.0.2)
    axiom-types (0.1.1)
    descendants_tracker (~> 0.0.4)
    ice_nine (~> 0.11.0)
    thread_safe (~> 0.3, >= 0.3.1)
    benchmark-ips (2.2.0)
    builder (3.2.2)
    coercible (1.0.0)
    descendants_tracker (~> 0.0.1)
    descendants_tracker (0.0.4)
    thread_safe (~> 0.3, >= 0.3.1)
    equalizer (0.0.11)
    i18n (0.7.0)
    ice_nine (0.11.1)
    json (1.8.3)
    memoizable (0.4.2)
    thread_safe (~> 0.3, >= 0.3.1)
    minitest (5.7.0)
    sqlite3 (1.3.10)
    thread_safe (0.3.5)
    transproc (0.3.0)
    tzinfo (1.2.2)
    thread_safe (~> 0.1)
    virtus (1.0.5)
    axiom-types (~> 0.1)
    coercible (~> 1.0)
    descendants_tracker (~> 0.0, >= 0.0.3)
    equalizer (~> 0.0, >= 0.0.9)

    PLATFORMS
    ruby

    DEPENDENCIES
    activerecord
    anima
    benchmark-ips
    sqlite3
    transproc
    virtus
    38 changes: 37 additions & 1 deletion anima_vs_virtus.rb → anima_vs_virtus_vs_activerecord.rb
    Original file line number Diff line number Diff line change
    @@ -1,12 +1,15 @@
    require 'anima'
    require 'transproc'
    require 'active_record'

    require 'virtus'

    require 'benchmark/ips'

    USERS = 1000.times.map { |i| { id: "#{i+1}", name: "User #{i+1}", age: "#{(i+1)*2}" } }

    # anima:

    module Mappings
    extend Transproc::Registry

    @@ -19,6 +22,8 @@ class AnimaUser
    include Anima.new(:id, :name, :age)
    end

    # virtus:

    class VirtusUser
    include Virtus.value_object

    @@ -29,14 +34,41 @@ class VirtusUser
    end
    end

    build_virtus_user = -> input { VirtusUser.new(input) }
    # activerecord:

    ActiveRecord::Base.logger = $STDOUT

    ActiveRecord::Base.establish_connection(
    :adapter => 'sqlite3',
    :database => ':memory:',
    )

    ActiveRecord::Schema.define do
    unless ActiveRecord::Base.connection.tables.include? 'active_record_users'
    create_table :active_record_users do |table|
    table.column :name, :string
    table.column :age, :integer
    end
    end
    end

    class ActiveRecordUser < ActiveRecord::Base
    end


    # benchmark:

    map_user_input = Mappings[:accept_keys, [:id, :name, :age]]
    .>> Mappings[:map_value, :id, Mappings[:to_integer]]
    .>> Mappings[:map_value, :age, Mappings[:to_integer]]

    build_anima_user = -> input { AnimaUser.new(map_user_input[input]) }

    build_virtus_user = -> input { VirtusUser.new(input) }

    build_active_record_user = -> input { ActiveRecordUser.new(input) }


    Benchmark.ips do |x|
    x.report "anima" do
    USERS.each { |attrs| build_anima_user[attrs] }
    @@ -46,5 +78,9 @@ class VirtusUser
    USERS.each { |attrs| build_virtus_user[attrs] }
    end

    x.report "activerecord" do
    USERS.each { |attrs| build_active_record_user[attrs] }
    end

    x.compare!
    end
    16 changes: 11 additions & 5 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,16 @@
    -- create_table(:active_record_users)
    -> 0.0019s
    Calculating -------------------------------------
    anima 8.000 i/100ms
    anima 5.000 i/100ms
    virtus 1.000 i/100ms
    activerecord 1.000 i/100ms
    -------------------------------------------------
    anima 83.732 (± 4.8%) i/s - 424.000
    virtus 6.409 (± 0.0%) i/s - 32.000
    anima 51.429 (± 3.9%) i/s - 260.000
    virtus 3.370 (± 0.0%) i/s - 17.000
    activerecord 6.468 (± 0.0%) i/s - 33.000

    Comparison:
    anima: 83.7 i/s
    virtus: 6.4 i/s - 13.06x slower
    anima: 51.4 i/s
    activerecord: 6.5 i/s - 7.95x slower
    virtus: 3.4 i/s - 15.26x slower

  2. @solnic solnic revised this gist Jul 16, 2015. 2 changed files with 10 additions and 3 deletions.
    3 changes: 0 additions & 3 deletions anima_vs_virtus.rb
    Original file line number Diff line number Diff line change
    @@ -37,9 +37,6 @@ class VirtusUser

    build_anima_user = -> input { AnimaUser.new(map_user_input[input]) }

    puts build_anima_user[USERS.first].inspect
    puts build_virtus_user[USERS.first].inspect

    Benchmark.ips do |x|
    x.report "anima" do
    USERS.each { |attrs| build_anima_user[attrs] }
    10 changes: 10 additions & 0 deletions gistfile1.txt
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    Calculating -------------------------------------
    anima 8.000 i/100ms
    virtus 1.000 i/100ms
    -------------------------------------------------
    anima 83.732 (± 4.8%) i/s - 424.000
    virtus 6.409 (± 0.0%) i/s - 32.000

    Comparison:
    anima: 83.7 i/s
    virtus: 6.4 i/s - 13.06x slower
  3. @solnic solnic created this gist Jul 16, 2015.
    53 changes: 53 additions & 0 deletions anima_vs_virtus.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,53 @@
    require 'anima'
    require 'transproc'

    require 'virtus'

    require 'benchmark/ips'

    USERS = 1000.times.map { |i| { id: "#{i+1}", name: "User #{i+1}", age: "#{(i+1)*2}" } }

    module Mappings
    extend Transproc::Registry

    import :accept_keys, from: Transproc::HashTransformations
    import :map_value, from: Transproc::HashTransformations
    import :to_integer, from: Transproc::Coercions
    end

    class AnimaUser
    include Anima.new(:id, :name, :age)
    end

    class VirtusUser
    include Virtus.value_object

    values do
    attribute :id, Integer
    attribute :name, String
    attribute :age, Integer
    end
    end

    build_virtus_user = -> input { VirtusUser.new(input) }

    map_user_input = Mappings[:accept_keys, [:id, :name, :age]]
    .>> Mappings[:map_value, :id, Mappings[:to_integer]]
    .>> Mappings[:map_value, :age, Mappings[:to_integer]]

    build_anima_user = -> input { AnimaUser.new(map_user_input[input]) }

    puts build_anima_user[USERS.first].inspect
    puts build_virtus_user[USERS.first].inspect

    Benchmark.ips do |x|
    x.report "anima" do
    USERS.each { |attrs| build_anima_user[attrs] }
    end

    x.report "virtus" do
    USERS.each { |attrs| build_virtus_user[attrs] }
    end

    x.compare!
    end