Skip to content

Instantly share code, notes, and snippets.

@jgaskins
Created February 1, 2018 21:46
Show Gist options
  • Save jgaskins/616f1489d76cd07b854fb8ec0dbeb9de to your computer and use it in GitHub Desktop.
Save jgaskins/616f1489d76cd07b854fb8ec0dbeb9de to your computer and use it in GitHub Desktop.
Primalize vs ActiveModel::Serializer
require 'active_model'
require 'benchmark/ips'
require 'active_model_serializers'
require 'primalize'
require 'pp'
class Model
include ActiveModel::Model
def read_attribute_for_serialization key
send(key)
end
end
class Movie < Model
attr_accessor :id, :title, :actors, :owner, :movie_types
def actor_ids
@actor_ids ||= actors.map(&:id)
end
def owner_id
owner.id
end
def movie_type_ids
@movie_type_ids ||= movie_types.map(&:id)
end
end
class Actor < Model
attr_accessor :id, :name, :email
end
class User < Model
attr_accessor :id, :name
end
class MovieType < Model
attr_accessor :id, :name
end
class MovieSerializer < ActiveModel::Serializer
attributes :id, :title, :actor_ids, :movie_type_ids, :owner_id
end
class MovieResponseSerializer < ActiveModel::Serializer
attributes :id, :title, :actor_ids, :movie_type_ids, :owner_id
has_many :actors
has_many :movie_types
belongs_to :owner, class_name: 'User'
end
class ActorSerializer < ActiveModel::Serializer
attributes :id, :name, :email
end
class UserSerializer < ActiveModel::Serializer
attributes :id, :name
end
class MovieTypeSerializer < ActiveModel::Serializer
attributes :id, :name
end
class MoviePrimalizer < Primalize::Single
attributes(
id: integer,
title: string,
actor_ids: array(integer),
movie_type_ids: array(integer),
owner_id: integer,
)
end
class ActorPrimalizer < Primalize::Single
attributes(
id: integer,
name: string,
email: string,
)
end
class UserPrimalizer < Primalize::Single
attributes(
id: integer,
name: string,
)
end
class MovieTypePrimalizer < Primalize::Single
attributes(
id: integer,
name: string,
)
end
class MoviesResponse < Primalize::Many
attributes(
movies: enumerable(MoviePrimalizer),
actors: enumerable(ActorPrimalizer),
users: enumerable(UserPrimalizer),
movie_types: enumerable(MovieTypePrimalizer),
)
end
def generate_movie
Movie.new(
id: rand(1_000_000_000),
title: 'Star Wars VIII: The Last Jedi',
actors: Array.new(rand(5)) { generate_actor },
owner: generate_user,
movie_types: Array.new(rand(1..4)) { generate_movie_type },
)
end
def generate_actor
@actors ||= {}
@actors[rand(50)] ||= Actor.new(
id: rand(1_000_000_000),
name: 'Carrie Fisher',
email: '[email protected]',
)
end
def generate_user
User.new(
id: rand(1234),
name: 'Jamie',
)
end
def generate_movie_type
@movie_types ||= {}
@movie_types[rand(10)] ||= MovieType.new(
id: rand(50),
name: 'Sci-fi',
)
end
movie = generate_movie
movies = Array.new(10) { generate_movie }
actors = movies.flat_map(&:actors).uniq
users = movies.flat_map(&:owner).uniq
movie_types = movies.flat_map(&:movie_types).uniq
pp MoviesResponse.new(
movies: movies,
actors: actors,
users: users,
movie_types: movie_types,
).call
pp ActiveModel::Serializer::CollectionSerializer.new(
movies.map { |movie| MovieResponseSerializer.new(movie) },
).as_json
puts 'Serialize model to hash'
Benchmark.ips do |x|
x.report('ams') { MovieSerializer.new(movie).to_h }
x.report('primalize') { MoviePrimalizer.new(movie).call }
x.compare!
end
puts 'Serialize model to JSON'
Benchmark.ips do |x|
x.report('ams') { MovieSerializer.new(movie).to_json }
x.report('primalize') { MoviePrimalizer.new(movie).to_json }
x.compare!
end
puts 'Serialize response to hash'
Benchmark.ips do |x|
x.report 'primalize' do
MoviesResponse.new(
movies: movies,
actors: actors,
users: users,
movie_types: movie_types,
).call
end
x.report 'ams' do
ActiveModel::Serializer::CollectionSerializer.new(
movies.map { |movie| MovieResponseSerializer.new(movie) },
).as_json
end
x.compare!
end
puts 'Serialize response to json'
Benchmark.ips do |x|
x.report 'ams' do
ActiveModel::Serializer::CollectionSerializer.new(
movies.map { |movie| MovieResponseSerializer.new(movie) },
).to_json
end
x.report 'primalize' do
MoviesResponse.new(
movies: movies,
actors: actors,
users: users,
movie_types: movie_types,
).to_json
end
x.compare!
end
Serialize model to hash
Warming up --------------------------------------
ams 6.303k i/100ms
primalize 8.660k i/100ms
Calculating -------------------------------------
ams 65.338k (± 4.2%) i/s - 327.756k in 5.025213s
primalize 90.516k (± 3.5%) i/s - 458.980k in 5.076961s
Comparison:
primalize: 90515.8 i/s
ams: 65338.4 i/s - 1.39x slower
Serialize model to JSON
Warming up --------------------------------------
ams 1.802k i/100ms
primalize 1.893k i/100ms
Calculating -------------------------------------
ams 18.620k (± 4.7%) i/s - 93.704k in 5.044650s
primalize 18.719k (± 5.2%) i/s - 94.650k in 5.071280s
Comparison:
primalize: 18719.0 i/s
ams: 18619.6 i/s - same-ish: difference falls within error
Serialize response to hash
Warming up --------------------------------------
primalize 417.000 i/100ms
ams 40.000 i/100ms
Calculating -------------------------------------
primalize 4.170k (± 3.8%) i/s - 20.850k in 5.007414s
ams 399.948 (± 3.5%) i/s - 2.000k in 5.006853s
Comparison:
primalize: 4170.1 i/s
ams: 399.9 i/s - 10.43x slower
Serialize response to json
Warming up --------------------------------------
ams 26.000 i/100ms
primalize 88.000 i/100ms
Calculating -------------------------------------
ams 273.387 (± 4.4%) i/s - 1.378k in 5.050290s
primalize 878.195 (± 4.3%) i/s - 4.400k in 5.019988s
Comparison:
primalize: 878.2 i/s
ams: 273.4 i/s - 3.21x slower
[{:id=>44720798,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[611411737],
:movie_type_ids=>[15],
:owner_id=>1023,
:actors=>
[{:id=>611411737,
:name=>"Carrie Fisher",
:email=>"[email protected]"}],
:movie_types=>[{:id=>15, :name=>"Sci-fi"}],
:owner=>{:id=>1023, :name=>"Jamie"}},
{:id=>875421260,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[],
:movie_type_ids=>[16, 11, 15],
:owner_id=>623,
:actors=>[],
:movie_types=>
[{:id=>16, :name=>"Sci-fi"},
{:id=>11, :name=>"Sci-fi"},
{:id=>15, :name=>"Sci-fi"}],
:owner=>{:id=>623, :name=>"Jamie"}},
{:id=>433376066,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[815279186, 788172241, 884209915],
:movie_type_ids=>[10],
:owner_id=>654,
:actors=>
[{:id=>815279186,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>788172241,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>884209915,
:name=>"Carrie Fisher",
:email=>"[email protected]"}],
:movie_types=>[{:id=>10, :name=>"Sci-fi"}],
:owner=>{:id=>654, :name=>"Jamie"}},
{:id=>102665941,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[888714126, 166529544, 333416253],
:movie_type_ids=>[42, 15, 47, 10],
:owner_id=>1133,
:actors=>
[{:id=>888714126,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>166529544,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>333416253,
:name=>"Carrie Fisher",
:email=>"[email protected]"}],
:movie_types=>
[{:id=>42, :name=>"Sci-fi"},
{:id=>15, :name=>"Sci-fi"},
{:id=>47, :name=>"Sci-fi"},
{:id=>10, :name=>"Sci-fi"}],
:owner=>{:id=>1133, :name=>"Jamie"}},
{:id=>573742525,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[604190144],
:movie_type_ids=>[47, 10, 3, 16],
:owner_id=>334,
:actors=>
[{:id=>604190144,
:name=>"Carrie Fisher",
:email=>"[email protected]"}],
:movie_types=>
[{:id=>47, :name=>"Sci-fi"},
{:id=>10, :name=>"Sci-fi"},
{:id=>3, :name=>"Sci-fi"},
{:id=>16, :name=>"Sci-fi"}],
:owner=>{:id=>334, :name=>"Jamie"}},
{:id=>854049375,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[383996039, 207858636, 507621145],
:movie_type_ids=>[16],
:owner_id=>961,
:actors=>
[{:id=>383996039,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>207858636,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>507621145,
:name=>"Carrie Fisher",
:email=>"[email protected]"}],
:movie_types=>[{:id=>16, :name=>"Sci-fi"}],
:owner=>{:id=>961, :name=>"Jamie"}},
{:id=>649519502,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[407513720, 518936796, 626235837, 815279186],
:movie_type_ids=>[15],
:owner_id=>1189,
:actors=>
[{:id=>407513720,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>518936796,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>626235837,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>815279186,
:name=>"Carrie Fisher",
:email=>"[email protected]"}],
:movie_types=>[{:id=>15, :name=>"Sci-fi"}],
:owner=>{:id=>1189, :name=>"Jamie"}},
{:id=>751495888,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[],
:movie_type_ids=>[41, 10, 41, 11],
:owner_id=>550,
:actors=>[],
:movie_types=>
[{:id=>41, :name=>"Sci-fi"},
{:id=>10, :name=>"Sci-fi"},
{:id=>41, :name=>"Sci-fi"},
{:id=>11, :name=>"Sci-fi"}],
:owner=>{:id=>550, :name=>"Jamie"}},
{:id=>178887483,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[],
:movie_type_ids=>[9, 47, 10, 3],
:owner_id=>411,
:actors=>[],
:movie_types=>
[{:id=>9, :name=>"Sci-fi"},
{:id=>47, :name=>"Sci-fi"},
{:id=>10, :name=>"Sci-fi"},
{:id=>3, :name=>"Sci-fi"}],
:owner=>{:id=>411, :name=>"Jamie"}},
{:id=>705400827,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[626235837],
:movie_type_ids=>[10, 9],
:owner_id=>185,
:actors=>
[{:id=>626235837,
:name=>"Carrie Fisher",
:email=>"[email protected]"}],
:movie_types=>[{:id=>10, :name=>"Sci-fi"}, {:id=>9, :name=>"Sci-fi"}],
:owner=>{:id=>185, :name=>"Jamie"}}]
{:movies=>
[{:id=>44720798,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[611411737],
:movie_type_ids=>[15],
:owner_id=>1023},
{:id=>875421260,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[],
:movie_type_ids=>[16, 11, 15],
:owner_id=>623},
{:id=>433376066,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[815279186, 788172241, 884209915],
:movie_type_ids=>[10],
:owner_id=>654},
{:id=>102665941,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[888714126, 166529544, 333416253],
:movie_type_ids=>[42, 15, 47, 10],
:owner_id=>1133},
{:id=>573742525,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[604190144],
:movie_type_ids=>[47, 10, 3, 16],
:owner_id=>334},
{:id=>854049375,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[383996039, 207858636, 507621145],
:movie_type_ids=>[16],
:owner_id=>961},
{:id=>649519502,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[407513720, 518936796, 626235837, 815279186],
:movie_type_ids=>[15],
:owner_id=>1189},
{:id=>751495888,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[],
:movie_type_ids=>[41, 10, 41, 11],
:owner_id=>550},
{:id=>178887483,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[],
:movie_type_ids=>[9, 47, 10, 3],
:owner_id=>411},
{:id=>705400827,
:title=>"Star Wars VIII: The Last Jedi",
:actor_ids=>[626235837],
:movie_type_ids=>[10, 9],
:owner_id=>185}],
:actors=>
[{:id=>611411737,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>815279186,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>788172241,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>884209915,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>888714126,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>166529544,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>333416253,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>604190144,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>383996039,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>207858636,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>507621145,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>407513720,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>518936796,
:name=>"Carrie Fisher",
:email=>"[email protected]"},
{:id=>626235837,
:name=>"Carrie Fisher",
:email=>"[email protected]"}],
:users=>
[{:id=>1023, :name=>"Jamie"},
{:id=>623, :name=>"Jamie"},
{:id=>654, :name=>"Jamie"},
{:id=>1133, :name=>"Jamie"},
{:id=>334, :name=>"Jamie"},
{:id=>961, :name=>"Jamie"},
{:id=>1189, :name=>"Jamie"},
{:id=>550, :name=>"Jamie"},
{:id=>411, :name=>"Jamie"},
{:id=>185, :name=>"Jamie"}],
:movie_types=>
[{:id=>15, :name=>"Sci-fi"},
{:id=>16, :name=>"Sci-fi"},
{:id=>11, :name=>"Sci-fi"},
{:id=>10, :name=>"Sci-fi"},
{:id=>42, :name=>"Sci-fi"},
{:id=>47, :name=>"Sci-fi"},
{:id=>3, :name=>"Sci-fi"},
{:id=>41, :name=>"Sci-fi"},
{:id=>9, :name=>"Sci-fi"},
{:id=>3, :name=>"Sci-fi"}]}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment