Skip to content

Instantly share code, notes, and snippets.

@midhun-thimmapuram
Last active June 7, 2022 13:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save midhun-thimmapuram/f6b45744e77f01750db64eb5f7a7a61e to your computer and use it in GitHub Desktop.
Save midhun-thimmapuram/f6b45744e77f01750db64eb5f7a7a61e to your computer and use it in GitHub Desktop.
blueprinter benchmark comparisons
# Current blueprinter benchmarks (0.25.3)
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'oj'
gem 'benchmark-ips', require: 'benchmark/ips'
gem 'kalibera'
gem 'benchmark-memory', require: 'benchmark/memory'
gem 'activesupport'
# https://github.com/procore/blueprinter
gem 'blueprinter'
end
require 'active_support'
require 'active_support/core_ext/object' # For Hash#deep_dup
# Define models
Issue = Struct.new(:id, :number, :title, :user, :labels) do
alias_method :read_attribute_for_serialization, :send
def label_ids
labels.map(&:id)
end
def user_id
user.id
end
end
User = Struct.new(:id, :login) do
alias_method :read_attribute_for_serialization, :send
end
Label = Struct.new(:id, :name, :color) do
alias_method :read_attribute_for_serialization, :send
end
# Define serializers
Blueprinter.configure do |config|
config.generator = Oj
config.sort_fields_by = :definition
end
module BluePrint
class Label < Blueprinter::Base
identifier :id
fields :name, :color
end
class User < Blueprinter::Base
identifier :id
field :login
end
class Issue < Blueprinter::Base
identifier :id
fields :number, :title
association :labels, blueprint: Label
association :user, blueprint: User
end
end
# Generate data
users = Array.new(10) { |i| User.new(i, "User #{i}") }
labels = Array.new(4) { |i| Label.new(i, "Label #{i}", 'ffffff') }
issues = Array.new(10_000) { |i| Issue.new(i, i, "Issue #{i}", users.sample, labels.sample(rand(2..4))) }
serializers = [
{
name: :blueprinter,
serializer: -> { BluePrint::Issue.render_as_hash(issues) },
output_inspector: ->(output) { output.first }
}
]
# Display output
serializers.each do |name:, serializer:, output_inspector:|
puts "\n#{name}:\n"
puts output_inspector.call(serializer.call).inspect
puts
end
# Run benchmarks
require 'benchmark'
Benchmark.bmbm do |b|
serializers.each do |name:, serializer:, **_other|
b.report(name, &serializer)
end
end
%i[ips memory].each do |bench|
Benchmark.send(bench) do |b|
b.config(time: 10, warmup: 5, stats: :bootstrap, confidence: 95) if b.respond_to?(:config)
serializers.each do |name:, serializer:, **_other|
b.report(name, &serializer)
end
b.compare!
end
end
# Optimised blueprinter benchmarks (https://github.com/midhun-thimmapuram/blueprinter)
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem 'oj'
gem 'benchmark-ips', require: 'benchmark/ips'
gem 'kalibera'
gem 'benchmark-memory', require: 'benchmark/memory'
gem 'activesupport'
# https://github.com/procore/blueprinter
gem 'blueprinter', :git => "git@github.com:/midhun-thimmapuram/blueprinter.git"
end
require 'active_support'
require 'active_support/core_ext/object' # For Hash#deep_dup
# Define models
Issue = Struct.new(:id, :number, :title, :user, :labels) do
alias_method :read_attribute_for_serialization, :send
def label_ids
labels.map(&:id)
end
def user_id
user.id
end
end
User = Struct.new(:id, :login) do
alias_method :read_attribute_for_serialization, :send
end
Label = Struct.new(:id, :name, :color) do
alias_method :read_attribute_for_serialization, :send
end
# Define serializers
Blueprinter.configure do |config|
config.generator = Oj
config.sort_fields_by = :definition
end
module BluePrint
class Label < Blueprinter::Base
identifier :id
fields :name, :color
end
class User < Blueprinter::Base
identifier :id
field :login
end
class Issue < Blueprinter::Base
identifier :id
fields :number, :title
association :labels, blueprint: Label
association :user, blueprint: User
end
end
# Generate data
users = Array.new(10) { |i| User.new(i, "User #{i}") }
labels = Array.new(4) { |i| Label.new(i, "Label #{i}", 'ffffff') }
issues = Array.new(10_000) { |i| Issue.new(i, i, "Issue #{i}", users.sample, labels.sample(rand(2..4))) }
serializers = [
{
name: :blueprinter,
serializer: -> { BluePrint::Issue.render_as_hash(issues) },
output_inspector: ->(output) { output.first }
}
]
# Display output
serializers.each do |name:, serializer:, output_inspector:|
puts "\n#{name}:\n"
puts output_inspector.call(serializer.call).inspect
puts
end
# Run benchmarks
require 'benchmark'
Benchmark.bmbm do |b|
serializers.each do |name:, serializer:, **_other|
b.report(name, &serializer)
end
end
%i[ips memory].each do |bench|
Benchmark.send(bench) do |b|
b.config(time: 10, warmup: 5, stats: :bootstrap, confidence: 95) if b.respond_to?(:config)
serializers.each do |name:, serializer:, **_other|
b.report(name, &serializer)
end
b.compare!
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment