From a24912cb1d34912a16aa27d952beff825e558f1f Mon Sep 17 00:00:00 2001
From: Michael Lovitt <michael@lovitt.net>
Date: Thu, 18 May 2017 15:38:30 -0500
Subject: Performance optimization for AttributeSet#deep_dup

Skip the call to #dup, since it does a shallow copy of attributes,
which is wasted effort, since #deep_dup then replaces that
shallow copy with a #deep_dup of the given attributes.

This change addresses slowness in ActiveRecord initialization
introduced starting in Rails 5.0.
---
 activerecord/lib/active_record/attribute_set.rb | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/attribute_set.rb b/activerecord/lib/active_record/attribute_set.rb
index 66b278219a..abe8e14f26 100644
--- a/activerecord/lib/active_record/attribute_set.rb
+++ b/activerecord/lib/active_record/attribute_set.rb
@@ -64,9 +64,7 @@ module ActiveRecord
     end
 
     def deep_dup
-      dup.tap do |copy|
-        copy.instance_variable_set(:@attributes, attributes.deep_dup)
-      end
+      self.class.new(attributes.deep_dup)
     end
 
     def initialize_dup(_)
-- 
cgit v1.2.3


From bfc62febac905412cdbcb7698d5a3b3ea5167af3 Mon Sep 17 00:00:00 2001
From: Michael Lovitt <michael@lovitt.net>
Date: Thu, 18 May 2017 15:43:49 -0500
Subject: Performance optimization for ActiveRecord#subclass_from_attributes

This change addresses slowness in ActiveRecord initialization
introduced starting in Rails 5.0.
---
 activerecord/lib/active_record/inheritance.rb | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb
index fbdaeaae51..236a65eba7 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -217,7 +217,7 @@ module ActiveRecord
         def subclass_from_attributes(attrs)
           attrs = attrs.to_h if attrs.respond_to?(:permitted?)
           if attrs.is_a?(Hash)
-            subclass_name = attrs.with_indifferent_access[inheritance_column]
+            subclass_name = attrs[inheritance_column] || attrs[inheritance_column.to_sym]
 
             if subclass_name.present?
               find_sti_class(subclass_name)
-- 
cgit v1.2.3


From 63dd12b7b83541d8a469a8e6aed1607d77f0d994 Mon Sep 17 00:00:00 2001
From: Michael Lovitt <michael@lovitt.net>
Date: Thu, 18 May 2017 15:52:45 -0500
Subject: Performance optimization for ActiveRecord#column_defaults

Memoize the #column_defaults class property, as ActiveRecord does
for other properties in this module.

This change addresses slowness in ActiveRecord initialization
introduced starting in Rails 5.0. This method's performance has not
changed with Rails 5, but it is now called much more frequently than
before: every time an STI model is instantiated.
---
 activerecord/lib/active_record/model_schema.rb | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb
index 54216caaaf..aa9087fae3 100644
--- a/activerecord/lib/active_record/model_schema.rb
+++ b/activerecord/lib/active_record/model_schema.rb
@@ -377,7 +377,7 @@ module ActiveRecord
       # default values when instantiating the Active Record object for this table.
       def column_defaults
         load_schema
-        _default_attributes.to_hash
+        @column_defaults ||= _default_attributes.to_hash
       end
 
       def _default_attributes # :nodoc:
@@ -466,6 +466,7 @@ module ActiveRecord
           @attribute_types = nil
           @content_columns = nil
           @default_attributes = nil
+          @column_defaults = nil
           @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
           @attributes_builder = nil
           @columns = nil
-- 
cgit v1.2.3


From fb6ccce80663dad034d86c472024076a8348a12f Mon Sep 17 00:00:00 2001
From: Michael Lovitt <michael@lovitt.net>
Date: Thu, 25 May 2017 17:14:33 -0500
Subject: Make #deep_dup use #allocate instead of #new

This change preserves the speedup made in a24912cb1d3 (by avoiding
the wasted shallow dup of @attributes) while ensuring that the
performance of #deep_dup won't be tied to the performance of #initialize
---
 activerecord/lib/active_record/attribute_set.rb | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

(limited to 'activerecord/lib')

diff --git a/activerecord/lib/active_record/attribute_set.rb b/activerecord/lib/active_record/attribute_set.rb
index abe8e14f26..01f9d815d5 100644
--- a/activerecord/lib/active_record/attribute_set.rb
+++ b/activerecord/lib/active_record/attribute_set.rb
@@ -64,7 +64,9 @@ module ActiveRecord
     end
 
     def deep_dup
-      self.class.new(attributes.deep_dup)
+      self.class.allocate.tap do |copy|
+        copy.instance_variable_set(:@attributes, attributes.deep_dup)
+      end
     end
 
     def initialize_dup(_)
-- 
cgit v1.2.3