Skip to content

Commit

Permalink
[Improve] Refactor benchmark: add comments, sort alphabetically
Browse files Browse the repository at this point in the history
  • Loading branch information
mediafinger committed Apr 16, 2021
1 parent 3bd00af commit 12640c6
Showing 1 changed file with 101 additions and 61 deletions.
162 changes: 101 additions & 61 deletions benchmark/local.rb
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
# Benchmark script to run varieties of JSON serializers
# Fetch Alba from local, otherwise fetch latest from RubyGems

# --- Bundle dependencies ---

require "bundler/inline"

gemfile(true) do
source "https://rubygems.org"

git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem "activerecord", "6.1.3"
gem "sqlite3"
gem "jbuilder"
gem "active_model_serializers"
gem "blueprinter"
gem "representable"
gem "activerecord", "6.1.3"
gem "alba", path: '../'
gem "oj"
gem "multi_json"
gem "benchmark-ips"
gem "jsonapi-serializer"
gem "blueprinter"
gem "jbuilder"
gem "jsonapi-serializer" # successor of fast_jsonapi
gem "multi_json"
gem "oj"
gem "representable"
gem "sqlite3"
end

# --- Test data model setup ---

require "active_record"
require "sqlite3"
require "logger"
require "oj"
require "sqlite3"
Oj.optimize_rails

ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
Expand Down Expand Up @@ -72,6 +75,8 @@ class User < ActiveRecord::Base
has_many :comments
end

# --- Alba serializers ---

require "alba"
Alba.backend = :oj

Expand All @@ -83,32 +88,13 @@ class AlbaCommentResource
class AlbaPostResource
include ::Alba::Resource
attributes :id, :body
many :comments, resource: AlbaCommentResource
attribute :commenter_names do |post|
post.commenters.pluck(:name)
end
many :comments, resource: AlbaCommentResource
end

require "jbuilder"
class Post
def to_builder
Jbuilder.new do |post|
post.call(self, :id, :body, :comments, :commenter_names)
end
end

def commenter_names
commenters.pluck(:name)
end
end

class Comment
def to_builder
Jbuilder.new do |comment|
comment.call(self, :id, :body)
end
end
end
# --- ActiveModelSerializer serializers ---

require "active_model_serializers"

Expand All @@ -118,13 +104,16 @@ class AMSCommentSerializer < ActiveModel::Serializer

class AMSPostSerializer < ActiveModel::Serializer
attributes :id, :body
has_many :comments, serializer: AMSCommentSerializer
attribute :commenter_names
has_many :comments, serializer: AMSCommentSerializer

def commenter_names
object.commenters.pluck(:name)
end
end

# --- Blueprint serializers ---

require "blueprinter"

class CommentBlueprint < Blueprinter::Base
Expand All @@ -134,33 +123,38 @@ class CommentBlueprint < Blueprinter::Base
class PostBlueprint < Blueprinter::Base
fields :id, :body, :commenter_names
association :comments, blueprint: CommentBlueprint

def commenter_names
commenters.pluck(:name)
end
end

require "representable"

class CommentRepresenter < Representable::Decorator
include Representable::JSON

property :id
property :body
end
# --- JBuilder serializers ---

class PostRepresenter < Representable::Decorator
include Representable::JSON
require "jbuilder"

property :id
property :body
property :commenter_names
collection :comments
class Post
def to_builder
Jbuilder.new do |post|
post.call(self, :id, :body, :commenter_names, :comments)
end
end

def commenter_names
commenters.pluck(:name)
end
end

class Comment
def to_builder
Jbuilder.new do |comment|
comment.call(self, :id, :body)
end
end
end

# --- JSONAPI:Serializer serializers / (successor of fast_jsonapi) ---

class JsonApiStandardCommentSerializer
include JSONAPI::Serializer

Expand All @@ -181,6 +175,8 @@ class JsonApiStandardPostSerializer
end
end

# --- JSONAPI:Serializer serializers that format the code the same flat way as the other gems here ---

# code to convert from JSON:API output to "flat" JSON, like the other serializers build
class JsonApiSameFormatSerializer
include JSONAPI::Serializer
Expand Down Expand Up @@ -209,7 +205,6 @@ class JsonApiSameFormatCommentSerializer < JsonApiSameFormatSerializer
end

class JsonApiSameFormatPostSerializer < JsonApiSameFormatSerializer
# set_type :post # optional
attribute :id
attribute :body
attribute :commenter_names
Expand All @@ -219,19 +214,42 @@ class JsonApiSameFormatPostSerializer < JsonApiSameFormatSerializer
end
end

# --- Representable serializers ---

require "representable"

class CommentRepresenter < Representable::Decorator
include Representable::JSON

property :id
property :body
end

class PostRepresenter < Representable::Decorator
include Representable::JSON

property :id
property :body
property :commenter_names
collection :comments

def commenter_names
commenters.pluck(:name)
end
end

# --- Test data creation ---

post = Post.create!(body: 'post')
user1 = User.create!(name: 'John')
user2 = User.create!(name: 'Jane')
post.comments.create!(commenter: user1, body: 'Comment1')
post.comments.create!(commenter: user2, body: 'Comment2')
post.reload

# --- Store the serializers in procs ---

alba = Proc.new { AlbaPostResource.new(post).serialize }
jbuilder = Proc.new { post.to_builder.target! }
ams = Proc.new { AMSPostSerializer.new(post, {}).to_json }
rails = Proc.new { ActiveSupport::JSON.encode(post.serializable_hash(include: :comments)) }
blueprinter = Proc.new { PostBlueprint.render(post) }
representable = Proc.new { PostRepresenter.new(post).to_json }
alba_inline = Proc.new do
Alba.serialize(post) do
attributes :id, :body
Expand All @@ -243,34 +261,56 @@ class JsonApiSameFormatPostSerializer < JsonApiSameFormatSerializer
end
end
end
ams = Proc.new { AMSPostSerializer.new(post, {}).to_json }
blueprinter = Proc.new { PostBlueprint.render(post) }
jbuilder = Proc.new { post.to_builder.target! }
jsonapi = proc { JsonApiStandardPostSerializer.new(post).to_json }
jsonapi_same_format = proc { JsonApiSameFormatPostSerializer.new(post).to_json }
rails = Proc.new { ActiveSupport::JSON.encode(post.serializable_hash(include: :comments)) }
representable = Proc.new { PostRepresenter.new(post).to_json }

# --- Execute the serializers to check their output ---

puts "Serializer outputs ----------------------------------"
{
alba: alba,
alba_inline: alba_inline,
ams: ams,
blueprinter: blueprinter,
jbuilder: jbuilder, # different order
jsonapi: jsonapi, # nested JSON:API format
jsonapi_same_format: jsonapi_same_format,
rails: rails,
representable: representable
}.each { |name, serializer| puts "#{name.to_s.ljust(24, ' ')} #{serializer.call}" }

[alba, jbuilder, rails, ams, blueprinter, representable, alba_inline, jsonapi, jsonapi_same_format].each {|x| puts x.call }
# --- Run the benchmarks ---

require 'benchmark'
time = 1000
Benchmark.bmbm do |x|
x.report(:alba) { time.times(&alba) }
x.report(:jbuilder) { time.times(&jbuilder) }
x.report(:alba_inline) { time.times(&alba_inline) }
x.report(:ams) { time.times(&ams) }
x.report(:rails) { time.times(&rails) }
x.report(:blueprinter) { time.times(&blueprinter) }
x.report(:representable) { time.times(&representable) }
x.report(:alba_inline) { time.times(&alba_inline) }
x.report(:jbuilder) { time.times(&jbuilder) }
x.report(:jsonapi) { time.times(&jsonapi) }
x.report(:jsonapi_same_format) { time.times(&jsonapi_same_format) }
x.report(:rails) { time.times(&rails) }
x.report(:representable) { time.times(&representable) }
end

require 'benchmark/ips'
Benchmark.ips do |x|
x.report(:alba, &alba)
x.report(:jbuilder, &jbuilder)
x.report(:alba_inline, &alba_inline)
x.report(:ams, &ams)
x.report(:rails, &rails)
x.report(:blueprinter, &blueprinter)
x.report(:representable, &representable)
x.report(:alba_inline, &alba_inline)
x.report(:jbuilder, &jbuilder)
x.report(:jsonapi, &jsonapi)
x.report(:jsonapi_same_format, &jsonapi_same_format)
x.report(:rails, &rails)
x.report(:representable, &representable)

x.compare!
end

0 comments on commit 12640c6

Please sign in to comment.