mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-22 22:06:50 +00:00
Optimised performance for attribute extraction
Disabled all instrumentation unless enabled explicitly
This commit is contained in:
parent
ad886495a1
commit
31ba6fbb08
1
.gitignore
vendored
1
.gitignore
vendored
@ -15,3 +15,4 @@ spec/reports
|
|||||||
test/tmp
|
test/tmp
|
||||||
test/version_tmp
|
test/version_tmp
|
||||||
tmp
|
tmp
|
||||||
|
*.swp
|
||||||
|
|||||||
5
Rakefile
5
Rakefile
@ -10,4 +10,9 @@ Rake::TestTask.new(:test) do |t|
|
|||||||
t.verbose = true
|
t.verbose = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc 'Benchmark'
|
||||||
|
task :bench do
|
||||||
|
load 'bench/perf.rb'
|
||||||
|
end
|
||||||
|
|
||||||
task :default => :test
|
task :default => :test
|
||||||
|
|||||||
52
bench/perf.rb
Normal file
52
bench/perf.rb
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
require "rubygems"
|
||||||
|
require "bundler/setup"
|
||||||
|
require "active_model_serializers"
|
||||||
|
require "active_support/json"
|
||||||
|
require "benchmark"
|
||||||
|
|
||||||
|
class User < Struct.new(:id,:name,:age,:about)
|
||||||
|
include ActiveModel::SerializerSupport
|
||||||
|
|
||||||
|
def fast_hash
|
||||||
|
h = {
|
||||||
|
id: read_attribute_for_serialization(:id),
|
||||||
|
name: read_attribute_for_serialization(:name),
|
||||||
|
about: read_attribute_for_serialization(:about)
|
||||||
|
}
|
||||||
|
h[:age] = read_attribute_for_serialization(:age) if age > 18
|
||||||
|
h
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class UserSerializer < ActiveModel::Serializer
|
||||||
|
attributes :id, :name, :age, :about
|
||||||
|
|
||||||
|
def include_age?
|
||||||
|
object.age > 18
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
u = User.new(1, "sam", 10, "about")
|
||||||
|
s = UserSerializer.new(u)
|
||||||
|
|
||||||
|
u2 = User.new(2, "sam", 20, "about")
|
||||||
|
s2 = UserSerializer.new(u2)
|
||||||
|
|
||||||
|
p s2.attributes
|
||||||
|
|
||||||
|
p s.attributes
|
||||||
|
|
||||||
|
|
||||||
|
n = 100000
|
||||||
|
|
||||||
|
Benchmark.bmbm {|x|
|
||||||
|
x.report("init") { n.times { UserSerializer.new(u) } }
|
||||||
|
x.report("fast_hash") { n.times { u.fast_hash } }
|
||||||
|
x.report("attributes") { n.times { UserSerializer.new(u).attributes } }
|
||||||
|
x.report("serializable_hash") { n.times { UserSerializer.new(u).serializable_hash } }
|
||||||
|
x.report("serializable_hash_with_instrumentation") { n.times { UserSerializer.new(u).serializable_hash_with_instrumentation } }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -93,6 +93,11 @@ module ActiveModel
|
|||||||
end
|
end
|
||||||
|
|
||||||
define_include_method attr
|
define_include_method attr
|
||||||
|
|
||||||
|
if self.method_defined? :_fast_attributes
|
||||||
|
undef :_fast_attributes
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def associate(klass, attrs) #:nodoc:
|
def associate(klass, attrs) #:nodoc:
|
||||||
@ -279,7 +284,15 @@ module ActiveModel
|
|||||||
|
|
||||||
# Returns a hash representation of the serializable
|
# Returns a hash representation of the serializable
|
||||||
# object without the root.
|
# object without the root.
|
||||||
def serializable_hash
|
def serializable_hash_without_instrumentation
|
||||||
|
return nil if @object.nil?
|
||||||
|
@node = attributes
|
||||||
|
include_associations! if _embed
|
||||||
|
@node
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
def serializable_hash_with_instrumentation
|
||||||
return nil if @object.nil?
|
return nil if @object.nil?
|
||||||
instrument(:serialize, :serializer => self.class.name) do
|
instrument(:serialize, :serializer => self.class.name) do
|
||||||
@node = attributes
|
@node = attributes
|
||||||
@ -290,6 +303,18 @@ module ActiveModel
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# disable all instrumentation on serializable_hash (performance will be better)
|
||||||
|
def self.disable_instrumentation!
|
||||||
|
alias_method :serializable_hash, :serializable_hash_without_instrumentation
|
||||||
|
end
|
||||||
|
|
||||||
|
# enable instrumentation for serializable_hash (performance may be impacted)
|
||||||
|
def self.enable_instrumentation!
|
||||||
|
alias_method :serializable_hash, :serializable_hash_with_instrumentation
|
||||||
|
end
|
||||||
|
|
||||||
|
disable_instrumentation!
|
||||||
|
|
||||||
def include_associations!
|
def include_associations!
|
||||||
_associations.each_key do |name|
|
_associations.each_key do |name|
|
||||||
include!(name) if include?(name)
|
include!(name) if include?(name)
|
||||||
@ -378,13 +403,19 @@ module ActiveModel
|
|||||||
# Returns a hash representation of the serializable
|
# Returns a hash representation of the serializable
|
||||||
# object attributes.
|
# object attributes.
|
||||||
def attributes
|
def attributes
|
||||||
hash = {}
|
_fast_attributes
|
||||||
|
rescue NameError
|
||||||
|
method = "def _fast_attributes\n"
|
||||||
|
|
||||||
|
method << " h = {}\n"
|
||||||
|
|
||||||
_attributes.each do |name,key|
|
_attributes.each do |name,key|
|
||||||
hash[key] = read_attribute_for_serialization(name) if include?(name)
|
method << " h[:#{key}] = read_attribute_for_serialization(:#{name}) if send #{INCLUDE_METHODS[name].inspect}\n"
|
||||||
end
|
end
|
||||||
|
method << " h\nend"
|
||||||
|
|
||||||
hash
|
self.class.class_eval method
|
||||||
|
_fast_attributes
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns options[:scope]
|
# Returns options[:scope]
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user