Skip to content

Commit

Permalink
chore: add benchmarks for alba and panko_serializer
Browse files Browse the repository at this point in the history
  • Loading branch information
ElMassimo committed Mar 27, 2023
1 parent 7e7cf5e commit b366276
Show file tree
Hide file tree
Showing 10 changed files with 279 additions and 10 deletions.
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@ end

group :development, :test do
gem 'active_model_serializers', '~> 0.8'
gem 'alba'
gem 'benchmark-ips'
gem 'benchmark-memory'
gem 'blueprinter', '~> 0.8'
gem 'memory_profiler'
gem 'mongoid'
gem 'panko_serializer'
gem 'pry-byebug', '~> 3.9'
gem 'rails' unless ENV['NO_RAILS']
gem 'rake', '~> 13.0'
Expand Down
6 changes: 6 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ GEM
minitest (~> 5.1)
tzinfo (~> 1.1)
zeitwerk (~> 2.2, >= 2.2.2)
alba (2.2.0)
ast (2.4.2)
benchmark-ips (2.8.3)
benchmark-memory (0.1.2)
Expand Down Expand Up @@ -128,6 +129,9 @@ GEM
nokogiri (1.14.2-x86_64-linux)
racc (~> 1.4)
oj (3.14.2)
panko_serializer (0.7.9)
activesupport
oj (> 3.11.0, < 4.0.0)
parallel (1.22.1)
parser (3.2.1.1)
ast (~> 2.4.1)
Expand Down Expand Up @@ -235,12 +239,14 @@ PLATFORMS

DEPENDENCIES
active_model_serializers (~> 0.8)
alba
benchmark-ips
benchmark-memory
blueprinter (~> 0.8)
memory_profiler
mongoid
oj_serializers!
panko_serializer
pry-byebug (~> 3.9)
rails
rake (~> 13.0)
Expand Down
41 changes: 33 additions & 8 deletions benchmarks/album_serializer_benchmark.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,37 @@

RSpec.describe 'AlbumSerializer', :benchmark do
context 'albums' do
before(:all) do |variable|
album = Album.abraxas
output = AlbumSerializer.one(album, special: true).to_json
expect(output).to eq LegacyAlbumSerializer.new(album, special: true).to_json
expect(output).to eq AlbumBlueprint.render(album, special: true)
expect(JSON.parse(output)).to eq JSON.parse AlbumPanko.new(context: { special: true }).serialize_to_json(album)
expect(JSON.parse(output)).to eq JSON.parse AlbumAlba.new(album, params: {special: true}).serialize
end

it 'serializing a model' do
album = Album.abraxas
expect(AlbumSerializer.one(album, special: true).to_json).to eq LegacyAlbumSerializer.new(album, special: true).to_json
expect(AlbumSerializer.one(album, special: true).to_json).to eq AlbumBlueprint.render(album, special: true)
Benchmark.ips do |x|
x.config(time: 5, warmup: 2)
x.report('oj_serializers as_hash') do
Oj.dump AlbumSerializer.one_as_hash(album)
end
x.report('oj_serializers') do
Oj.dump AlbumSerializer.one_as_json(album)
end
x.report('oj_serializers as_hash') do
Oj.dump AlbumSerializer.one_as_hash(album)
x.report('panko') do
AlbumPanko.new.serialize_to_json(album)
end
x.report('blueprinter') do
AlbumBlueprint.render(album)
end
x.report('active_model_serializers') do
Oj.dump LegacyAlbumSerializer.new(album)
end
x.report('alba') do
AlbumAlba.new(album).serialize
end
x.compare!
end
end
Expand All @@ -30,18 +43,24 @@
albums = 100.times.map { Album.abraxas }
Benchmark.ips do |x|
x.config(time: 5, warmup: 2)
x.report('oj_serializers as_hash') do
Oj.dump AlbumSerializer.many_as_hash(albums)
end
x.report('oj_serializers') do
Oj.dump AlbumSerializer.many_as_json(albums)
end
x.report('oj_serializers as_hash') do
Oj.dump AlbumSerializer.many_as_hash(albums)
x.report('panko') do
Panko::ArraySerializer.new(albums, each_serializer: AlbumPanko).to_json
end
x.report('blueprinter') do
AlbumBlueprint.render(albums)
end
x.report('active_model_serializers') do
Oj.dump(albums.map { |album| LegacyAlbumSerializer.new(album) })
end
x.report('alba') do
AlbumAlba.new(albums).serialize
end
x.compare!
end
end
Expand All @@ -50,18 +69,24 @@
albums = 1000.times.map { Album.abraxas }
Benchmark.ips do |x|
x.config(time: 5, warmup: 2)
x.report('oj_serializers as_hash') do
Oj.dump AlbumSerializer.many_as_hash(albums)
end
x.report('oj_serializers') do
Oj.dump AlbumSerializer.many_as_json(albums)
end
x.report('oj_serializers as_hash') do
Oj.dump AlbumSerializer.many_as_hash(albums)
x.report('panko') do
Panko::ArraySerializer.new(albums, each_serializer: AlbumPanko).to_json
end
x.report('blueprinter') do
AlbumBlueprint.render(albums)
end
x.report('active_model_serializers') do
Oj.dump(albums.map { |album| LegacyAlbumSerializer.new(album) })
end
x.report('alba') do
AlbumAlba.new(albums).serialize
end
x.compare!
end
end
Expand Down
63 changes: 63 additions & 0 deletions benchmarks/game_serializer_benchmark.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# frozen_string_literal: true

require 'benchmark_helper'
require 'support/models/sql'

class PlayerPanko < Panko::Serializer
attributes :id, :first_name, :last_name, :full_name

def id
object.id if object.persisted?
end

def full_name
object.full_name
end
end

# NOTE: This example is quite contrived. Finding good test cases is as hard as
# finding good names.
class ScoresPanko < Panko::Serializer
attributes :high_score, :score
end

class GamePanko < Panko::Serializer
attributes :id, :name

has_one :scores, serializer: ScoresPanko

has_one :best_player, serializer: PlayerPanko
has_many :players, serializer: PlayerPanko

def id
object.id if object.persisted?
end
end

Game.prepend Module.new {
def scores
self
end
}

RSpec.describe 'GameSerializer', :benchmark do
context 'albums' do
it 'serializing a model' do
game = Game.example

Benchmark.ips do |x|
x.config(time: 5, warmup: 2)
x.report('oj_serializers as_hash') do
Oj.dump GameSerializer.one_as_hash(game)
end
x.report('oj_serializers') do
Oj.dump GameSerializer.one_as_json(game)
end
x.report('panko') do
GamePanko.new.serialize_to_json(game)
end
x.compare!
end
end
end
end
6 changes: 6 additions & 0 deletions benchmarks/model_serializer_benchmark.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
x.report('oj_serializers hash') do
Oj.dump ModelSerializer.many_as_hash(albums)
end
x.report('panko') do
Panko::ArraySerializer.new(albums, each_serializer: ModelPanko).to_json
end
x.report('alba') do
ModelAlba.new(albums).serialize
end
x.report('blueprinter') do
ModelBlueprint.render(albums)
end
Expand Down
6 changes: 6 additions & 0 deletions benchmarks/option_serializer_benchmark.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
x.report('write_models') do
Oj.dump OptionSerializer.write_models(albums)
end
x.report('alba') do
OptionSerializer::Alba.new(albums).serialize
end
x.report('panko') do
Panko::ArraySerializer.new(albums, each_serializer: OptionSerializer::Panko).to_json
end
x.report('active_model_serializers') do
Oj.dump(albums.map { |album| OptionSerializer::AMS.new(album) })
end
Expand Down
4 changes: 2 additions & 2 deletions spec/support/models/sql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ def full_name
end

class PlayerSerializer < Oj::Serializer
attributes :id, if: -> { player.persisted? }
identifier
attributes :first_name, :last_name, :full_name
end

Expand All @@ -68,7 +68,7 @@ class ScoresSerializer < Oj::Serializer
end

class GameSerializer < Oj::Serializer
attributes :id, if: -> { game.persisted? }
identifier
attributes :name

flat_one :game, serializer: ScoresSerializer
Expand Down
54 changes: 54 additions & 0 deletions spec/support/serializers/alba.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# frozen_string_literal: true

require 'alba'

Alba.backend = :oj_rails
Alba.inflector = :active_support

class BaseAlba
include Alba::Resource
transform_keys :lower_camel
end

class SongAlba < BaseAlba
attributes :id, if: proc { |song| !song.new_record? }

attributes(
:track,
:name,
:composers,
)

def composers(song)
song.composer&.split(', ')
end
end

class AlbumAlba < BaseAlba
attributes :id, if: proc { |album| !album.new_record? }

attributes(
:name,
:genres,
)

attributes :release, if: proc { |album| album.released? }
def release(album)
album.release_date.strftime('%B %d, %Y')
end

attributes :special, if: proc { params[:special] }
def special(album)
params[:special]
end

many :songs, resource: SongAlba
many :other_songs, resource: SongAlba, if: proc { |album| album.other_songs.present? }
end

class ModelAlba < BaseAlba
attributes(
:id,
:name,
)
end
26 changes: 26 additions & 0 deletions spec/support/serializers/option_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,22 @@
require 'oj_serializers'
require 'active_model_serializers'
require 'blueprinter'
require 'panko_serializer'
require_relative 'alba'

module OptionSerializer
class Alba
include ::Alba::Resource

attribute :label do |object|
object.attributes['name']
end

attribute :value do |object|
object.attributes['_id']
end
end

class AMS < ActiveModel::Serializer
attributes(
:label,
Expand Down Expand Up @@ -40,6 +54,18 @@ class Oj < Oj::Serializer
end
end

class Panko < Panko::Serializer
attributes(:label, :value)

def label
@object.attributes['name']
end

def value
@object.attributes['_id']
end
end

def self.write_models(models)
writer = ::Oj::StringWriter.new(mode: :wab)

Expand Down
Loading

0 comments on commit b366276

Please sign in to comment.