Created
February 1, 2018 21:46
-
-
Save jgaskins/616f1489d76cd07b854fb8ec0dbeb9de to your computer and use it in GitHub Desktop.
Primalize vs ActiveModel::Serializer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[{: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"}}] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{: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