From 613060d106f2d3bf7350bab540c952b1567ad66b Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Wed, 29 May 2019 06:45:34 +0900 Subject: Avoid making extra 5 arrays in each `save` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Each `save` calls `all_timestamp_attributes_in_model` to fill timestamp columns. Allthough the `all_timestamp_attributes_in_model` returns the same value every time, the `all_timestamp_attributes_in_model` makes extra 5 arrays every time. This avoids the making extra 5 arrays by memoizing the result, it makes `save` economical and a bit faster. https://gist.github.com/kamipo/1ddad2235073f508637bf9a72d64bb83 Before (2a015f6c0be0593a624b0c800e5335319ac4c660): ``` {["~/rails/activerecord/lib/active_record/timestamp.rb", 76, :T_ARRAY]=>[1000, 0, 341, 0, 1, 13640], ["~/rails/activerecord/lib/active_record/timestamp.rb", 64, :T_ARRAY]=>[1000, 0, 341, 0, 1, 13640], ["~/rails/activerecord/lib/active_record/timestamp.rb", 80, :T_ARRAY]=>[1000, 0, 341, 0, 1, 13640], ["~/rails/activerecord/lib/active_record/timestamp.rb", 68, :T_ARRAY]=>[1000, 0, 341, 0, 1, 13640], ["~/rails/activerecord/lib/active_record/timestamp.rb", 73, :T_ARRAY]=>[1000, 0, 341, 0, 1, 13640]} Warming up -------------------------------------- User.create * 10 36.000 i/100ms Calculating ------------------------------------- User.create * 10 353.644 (± 7.4%) i/s - 1.764k in 5.021876s ``` After (this change): ``` {["~/rails/activerecord/lib/active_record/timestamp.rb", 83, :T_ARRAY]=>[1, 0, 1, 1, 1, 40], ["~/rails/activerecord/lib/active_record/timestamp.rb", 87, :T_ARRAY]=>[1, 0, 1, 1, 1, 40], ["~/rails/activerecord/lib/active_record/timestamp.rb", 64, :T_ARRAY]=>[1, 1, 1, 1, 1, 0], ["~/rails/activerecord/lib/active_record/timestamp.rb", 69, :T_ARRAY]=>[1, 1, 1, 1, 1, 0], ["~/rails/activerecord/lib/active_record/timestamp.rb", 74, :T_ARRAY]=>[1, 1, 1, 1, 1, 0]} Warming up -------------------------------------- User.create * 10 37.000 i/100ms Calculating ------------------------------------- User.create * 10 380.063 (± 7.1%) i/s - 1.924k in 5.097917s ``` --- activerecord/lib/active_record/timestamp.rb | 42 ++++++++++++++++++----------- 1 file changed, 26 insertions(+), 16 deletions(-) (limited to 'activerecord/lib/active_record') diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index 04a1c03474..a5862ae06b 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -59,19 +59,26 @@ module ActiveRecord attribute_names.index_with(time || current_time_from_proper_timezone) end - private - def timestamp_attributes_for_create_in_model - timestamp_attributes_for_create.select { |c| column_names.include?(c) } - end + def timestamp_attributes_for_create_in_model + @timestamp_attributes_for_create_in_model ||= + (timestamp_attributes_for_create & column_names).freeze + end - def timestamp_attributes_for_update_in_model - timestamp_attributes_for_update.select { |c| column_names.include?(c) } - end + def timestamp_attributes_for_update_in_model + @timestamp_attributes_for_update_in_model ||= + (timestamp_attributes_for_update & column_names).freeze + end - def all_timestamp_attributes_in_model - timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model - end + def all_timestamp_attributes_in_model + @all_timestamp_attributes_in_model ||= + (timestamp_attributes_for_create_in_model + timestamp_attributes_for_update_in_model).freeze + end + def current_time_from_proper_timezone + default_timezone == :utc ? Time.now.utc : Time.now + end + + private def timestamp_attributes_for_create ["created_at", "created_on"] end @@ -80,8 +87,11 @@ module ActiveRecord ["updated_at", "updated_on"] end - def current_time_from_proper_timezone - default_timezone == :utc ? Time.now.utc : Time.now + def reload_schema_from_cache + @timestamp_attributes_for_create_in_model = nil + @timestamp_attributes_for_update_in_model = nil + @all_timestamp_attributes_in_model = nil + super end end @@ -124,19 +134,19 @@ module ActiveRecord end def timestamp_attributes_for_create_in_model - self.class.send(:timestamp_attributes_for_create_in_model) + self.class.timestamp_attributes_for_create_in_model end def timestamp_attributes_for_update_in_model - self.class.send(:timestamp_attributes_for_update_in_model) + self.class.timestamp_attributes_for_update_in_model end def all_timestamp_attributes_in_model - self.class.send(:all_timestamp_attributes_in_model) + self.class.all_timestamp_attributes_in_model end def current_time_from_proper_timezone - self.class.send(:current_time_from_proper_timezone) + self.class.current_time_from_proper_timezone end def max_updated_column_timestamp -- cgit v1.2.3