From d29d4598972e85df7ee42f5aa969b51d1b14d615 Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Fri, 14 Jun 2019 08:50:24 +0900 Subject: Avoid redundant `time.getutc` call if it is already utc time object Currently `type.serialize` and `connection.{quote|type_cast}` for a time object always does `time.getutc` call regardless of whether it is already utc time object or not, that duplicated proccess (`connection.type_cast(type.serialize(time))`) allocates extra/useless time objects for each type casting. This avoids that redundant `time.getutc` call if it is already utc time object. In the case of a model has timestamps (`created_at` and `updated_at`), it avoids 6,000 time objects allocation for 1,000 times `model.save`. ```ruby ObjectSpace::AllocationTracer.setup(%i{path line type}) pp ObjectSpace::AllocationTracer.trace { 1_000.times { User.create } }.select { |k, _| k[0].end_with?("quoting.rb", "time_value.rb") } ``` Before (c104bfe424e6cebe9c8e85a38515327a6c88b1f8): ``` {["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb", 203, :T_ARRAY]=>[1004, 0, 778, 0, 1, 0], ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb", 220, :T_STRING]=>[2, 0, 2, 1, 1, 0], ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb", 209, :T_ARRAY]=>[8, 0, 8, 1, 1, 0], ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb", 57, :T_ARRAY]=>[4, 0, 4, 1, 1, 0], ["~/rails/activemodel/lib/active_model/type/helpers/time_value.rb", 17, :T_DATA]=>[4000, 0, 3096, 0, 1, 0], ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb", 120, :T_DATA]=>[2000, 0, 1548, 0, 1, 0], ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb", 126, :T_STRING]=>[4000, 0, 3096, 0, 1, 0]} ``` After (this change): ``` {["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb", 203, :T_ARRAY]=>[1004, 0, 823, 0, 1, 0], ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb", 220, :T_STRING]=>[2, 0, 2, 1, 1, 0], ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb", 209, :T_ARRAY]=>[8, 0, 8, 1, 1, 0], ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb", 57, :T_ARRAY]=>[4, 0, 4, 1, 1, 0], ["~/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb", 126, :T_STRING]=>[2000, 0, 1638, 0, 1, 0]} ``` --- activemodel/lib/active_model/type/helpers/time_value.rb | 8 ++++---- activemodel/lib/active_model/type/value.rb | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'activemodel/lib') diff --git a/activemodel/lib/active_model/type/helpers/time_value.rb b/activemodel/lib/active_model/type/helpers/time_value.rb index 508fe77531..075e906034 100644 --- a/activemodel/lib/active_model/type/helpers/time_value.rb +++ b/activemodel/lib/active_model/type/helpers/time_value.rb @@ -11,10 +11,10 @@ module ActiveModel value = apply_seconds_precision(value) if value.acts_like?(:time) - zone_conversion_method = is_utc? ? :getutc : :getlocal - - if value.respond_to?(zone_conversion_method) - value = value.send(zone_conversion_method) + if is_utc? + value = value.getutc if value.respond_to?(:getutc) && !value.utc? + else + value = value.getlocal if value.respond_to?(:getlocal) end end diff --git a/activemodel/lib/active_model/type/value.rb b/activemodel/lib/active_model/type/value.rb index 994d135b7b..788ded3e96 100644 --- a/activemodel/lib/active_model/type/value.rb +++ b/activemodel/lib/active_model/type/value.rb @@ -110,7 +110,7 @@ module ActiveModel [self.class, precision, scale, limit].hash end - def assert_valid_value(*) + def assert_valid_value(_) end private -- cgit v1.2.3