Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid redundant time.getutc call if it is already utc time object #36508

Merged
merged 1 commit into from Jun 18, 2019

Conversation

@kamipo
Copy link
Member

@kamipo kamipo commented Jun 17, 2019

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.

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 (c104bfe):

{["~/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]}
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 (c104bfe):

```
{["~/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]}
```
@kamipo kamipo merged commit aeba121 into rails:master Jun 18, 2019
2 checks passed
Loading
@kamipo kamipo deleted the avoid_getutc branch Jun 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

1 participant