mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge pull request #33223 from rails/homogeneous-allocation
Speed up homogeneous AR lists / reduce allocations
This commit is contained in:
commit
316513177c
5 changed files with 49 additions and 2 deletions
|
@ -344,6 +344,28 @@ module ActiveRecord
|
||||||
self
|
self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# Initializer used for instantiating objects that have been read from the
|
||||||
|
# database. +attributes+ should be an attributes object, and unlike the
|
||||||
|
# `initialize` method, no assignment calls are made per attribute.
|
||||||
|
#
|
||||||
|
# :nodoc:
|
||||||
|
def init_from_db(attributes)
|
||||||
|
init_internals
|
||||||
|
|
||||||
|
@new_record = false
|
||||||
|
@attributes = attributes
|
||||||
|
|
||||||
|
self.class.define_attribute_methods
|
||||||
|
|
||||||
|
yield self if block_given?
|
||||||
|
|
||||||
|
_run_find_callbacks
|
||||||
|
_run_initialize_callbacks
|
||||||
|
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
##
|
##
|
||||||
# :method: clone
|
# :method: clone
|
||||||
# Identical to Ruby's clone method. This is a "shallow" copy. Be warned that your attributes are not copied.
|
# Identical to Ruby's clone method. This is a "shallow" copy. Be warned that your attributes are not copied.
|
||||||
|
|
|
@ -67,8 +67,18 @@ module ActiveRecord
|
||||||
# how this "single-table" inheritance mapping is implemented.
|
# how this "single-table" inheritance mapping is implemented.
|
||||||
def instantiate(attributes, column_types = {}, &block)
|
def instantiate(attributes, column_types = {}, &block)
|
||||||
klass = discriminate_class_for_record(attributes)
|
klass = discriminate_class_for_record(attributes)
|
||||||
|
instantiate_instance_of(klass, attributes, column_types, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Given a class, an attributes hash, +instantiate_instance_of+ returns a
|
||||||
|
# new instance of the class. Accepts only keys as strings.
|
||||||
|
#
|
||||||
|
# This is private, don't call it. :)
|
||||||
|
#
|
||||||
|
# :nodoc:
|
||||||
|
def instantiate_instance_of(klass, attributes, column_types = {}, &block)
|
||||||
attributes = klass.attributes_builder.build_from_database(attributes, column_types)
|
attributes = klass.attributes_builder.build_from_database(attributes, column_types)
|
||||||
klass.allocate.init_with("attributes" => attributes, "new_record" => false, &block)
|
klass.allocate.init_from_db(attributes, &block)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Updates an object (or multiple objects) and saves it to the database, if validations pass.
|
# Updates an object (or multiple objects) and saves it to the database, if validations pass.
|
||||||
|
|
|
@ -49,7 +49,12 @@ module ActiveRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
message_bus.instrument("instantiation.active_record", payload) do
|
message_bus.instrument("instantiation.active_record", payload) do
|
||||||
result_set.map { |record| instantiate(record, column_types, &block) }
|
if result_set.includes_column?(inheritance_column)
|
||||||
|
result_set.map { |record| instantiate(record, column_types, &block) }
|
||||||
|
else
|
||||||
|
# Instantiate a homogeneous set
|
||||||
|
result_set.map { |record| instantiate_instance_of(self, record, column_types, &block) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,11 @@ module ActiveRecord
|
||||||
@column_types = column_types
|
@column_types = column_types
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Returns true if this result set includes the column named +name+
|
||||||
|
def includes_column?(name)
|
||||||
|
@columns.include? name
|
||||||
|
end
|
||||||
|
|
||||||
# Returns the number of elements in the rows array.
|
# Returns the number of elements in the rows array.
|
||||||
def length
|
def length
|
||||||
@rows.length
|
@rows.length
|
||||||
|
|
|
@ -12,6 +12,11 @@ module ActiveRecord
|
||||||
])
|
])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
test "includes_column?" do
|
||||||
|
assert result.includes_column?("col_1")
|
||||||
|
assert_not result.includes_column?("foo")
|
||||||
|
end
|
||||||
|
|
||||||
test "length" do
|
test "length" do
|
||||||
assert_equal 3, result.length
|
assert_equal 3, result.length
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue