benchmark/collection.rb in alba-2.0.1 vs benchmark/collection.rb in alba-2.1.0

- old
+ new

@@ -1,91 +1,10 @@ # Benchmark script to run varieties of JSON serializers # Fetch Alba from local, otherwise fetch latest from RubyGems -# --- Bundle dependencies --- +require_relative 'prep' -require "bundler/inline" - -gemfile(true) do - source "https://rubygems.org" - git_source(:github) { |repo| "https://github.com/#{repo}.git" } - - gem "active_model_serializers" - gem "activerecord", "6.1.3" - gem "alba", path: '../' - gem "benchmark-ips" - gem "benchmark-memory" - gem "blueprinter" - gem "fast_serializer_ruby" - gem "jbuilder" - gem 'turbostreamer' - gem "jserializer" - gem "multi_json" - gem "panko_serializer" - gem "pg" - gem "primalize" - gem "oj" - gem "representable" - gem "simple_ams" - gem "sqlite3" -end - -# --- Test data model setup --- - -require "pg" -require "active_record" -require "active_record/connection_adapters/postgresql_adapter" -require "logger" -require "oj" -require "sqlite3" -Oj.optimize_rails - -ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:") -# ActiveRecord::Base.logger = Logger.new($stdout) - -ActiveRecord::Schema.define do - create_table :posts, force: true do |t| - t.string :body - end - - create_table :comments, force: true do |t| - t.integer :post_id - t.string :body - t.integer :commenter_id - end - - create_table :users, force: true do |t| - t.string :name - end -end - -class Post < ActiveRecord::Base - has_many :comments - has_many :commenters, through: :comments, class_name: 'User', source: :commenter - - def attributes - {id: nil, body: nil, commenter_names: commenter_names} - end - - def commenter_names - commenters.pluck(:name) - end -end - -class Comment < ActiveRecord::Base - belongs_to :post - belongs_to :commenter, class_name: 'User' - - def attributes - {id: nil, body: nil} - end -end - -class User < ActiveRecord::Base - has_many :comments -end - # --- Alba serializers --- require "alba" class AlbaCommentResource @@ -158,34 +77,10 @@ end has_many :comments, serializer: FastSerializerCommentResource end -# --- JBuilder serializers --- - -require "jbuilder" - -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 - # --- Jserializer serializers --- require 'jserializer' class JserializerCommentSerializer < Jserializer::Base @@ -218,35 +113,10 @@ def commenter_names object.commenters.pluck(:name) end end -# --- Primalize serializers --- -# -class PrimalizeCommentResource < Primalize::Single - attributes id: integer, body: string -end - -class PrimalizePostResource < Primalize::Single - alias post object - - attributes( - id: integer, - body: string, - comments: array(primalize(PrimalizeCommentResource)), - commenter_names: array(string), - ) - - def commenter_names - post.commenters.pluck(:name) - end -end - -class PrimalizePostsResource < Primalize::Many - attributes posts: enumerable(PrimalizePostResource) -end - # --- Representable serializers --- require "representable" class CommentRepresenter < Representable::Decorator @@ -347,17 +217,10 @@ end end ams = Proc.new { ActiveModelSerializers::SerializableResource.new(posts, {each_serializer: AMSPostSerializer}).to_json } blueprinter = Proc.new { PostBlueprint.render(posts) } fast_serializer = Proc.new { FastSerializerPostResource.new(posts).to_json } -jbuilder = Proc.new do - Jbuilder.new do |json| - json.array!(posts) do |post| - json.post post.to_builder - end - end.target! -end jserializer = Proc.new { JserializerPostSerializer.new(posts, is_collection: true).to_json } panko = proc { Panko::ArraySerializer.new(posts, each_serializer: PankoPostSerializer).to_json } primalize = proc { PrimalizePostsResource.new(posts: posts).to_json } rails = Proc.new do ActiveSupport::JSON.encode(posts.map{ |post| post.serializable_hash(include: :comments) }) @@ -366,40 +229,41 @@ simple_ams = Proc.new { SimpleAMS::Renderer::Collection.new(posts, serializer: SimpleAMSPostSerializer).to_json } turbostreamer = Proc.new { TurbostreamerSerializer.new(posts).to_json } # --- Execute the serializers to check their output --- GC.disable -puts "Serializer outputs ----------------------------------" +puts "Checking outputs..." +correct = alba.call +parsed_correct = JSON.parse(correct) { - alba: alba, alba_inline: alba_inline, ams: ams, blueprinter: blueprinter, fast_serializer: fast_serializer, - jbuilder: jbuilder, # different order jserializer: jserializer, panko: panko, - primalize: primalize, rails: rails, representable: representable, simple_ams: simple_ams, turbostreamer: turbostreamer -}.each { |name, serializer| puts "#{name.to_s.ljust(24, ' ')} #{serializer.call}" } +}.each do |name, serializer| + result = serializer.call + parsed_result = JSON.parse(result) + puts "#{name} yields wrong output: #{parsed_result}" unless parsed_result == parsed_correct +end # --- Run the benchmarks --- require 'benchmark/ips' Benchmark.ips do |x| x.report(:alba, &alba) x.report(:alba_inline, &alba_inline) x.report(:ams, &ams) x.report(:blueprinter, &blueprinter) x.report(:fast_serializer, &fast_serializer) - x.report(:jbuilder, &jbuilder) x.report(:jserializer, &jserializer) x.report(:panko, &panko) - x.report(:primalize, &primalize) x.report(:rails, &rails) x.report(:representable, &representable) x.report(:simple_ams, &simple_ams) x.report(:turbostreamer, &turbostreamer) @@ -412,13 +276,11 @@ x.report(:alba, &alba) x.report(:alba_inline, &alba_inline) x.report(:ams, &ams) x.report(:blueprinter, &blueprinter) x.report(:fast_serializer, &fast_serializer) - x.report(:jbuilder, &jbuilder) x.report(:jserializer, &jserializer) x.report(:panko, &panko) - x.report(:primalize, &primalize) x.report(:rails, &rails) x.report(:representable, &representable) x.report(:simple_ams, &simple_ams) x.report(:turbostreamer, &turbostreamer)