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

Speed up Time.zone.now #26359

Merged
merged 1 commit into from Oct 5, 2016

Conversation

Projects
None yet
4 participants
@maclover7
Member

maclover7 commented Sep 1, 2016

@amatsuda, during his RailsConf talk this past year, presented a
benchmark that showed Time.zone.now (an Active Support joint)
performing 24.97x slower than Ruby's Time.now. Rails master appears to
be a bit faster than that, currently clocking in at 18.25x slower than
Time.now. Here's the exact benchmark data for that:

Warming up --------------------------------------
            Time.now   127.923k i/100ms
       Time.zone.now    10.275k i/100ms
Calculating -------------------------------------
            Time.now      1.946M (± 5.9%) i/s -      9.722M in   5.010236s
       Time.zone.now    106.625k (± 4.3%) i/s -    534.300k in   5.020343s

Comparison:
            Time.now:  1946220.1 i/s
       Time.zone.now:   106625.5 i/s - 18.25x slower

What if I told you we could make Time.zone.now even faster? Well,
that's exactly what this patch accomplishes. When creating ActiveSupport::TimeWithZone
objects, we try to convert the provided time to be in a UTC format. All
this patch does is, in the method where we convert a provided time to
UTC, check if the provided time is already UTC, and is a Time object
and then return early if that is the case, This sidesteps having to continue on,
and create a new Time object from scratch. Here's the exact benchmark
data for my patch:

Warming up --------------------------------------
            Time.now   124.870k i/100ms
       Time.zone.now    27.344k i/100ms
Calculating -------------------------------------
            Time.now      1.924M (± 5.6%) i/s -      9.615M in   5.011704s
       Time.zone.now    310.385k (± 4.3%) i/s -      1.559M in   5.030432s

Comparison:
            Time.now:  1923815.5 i/s
       Time.zone.now:   310384.7 i/s - 6.20x slower

With this patch, we go from Time.zone.now being 18.25x slower than
Time.now to only being 6.20x slower than Time.now. I'd obviously love some verification on this patch, since these numbers sound pretty interesting... :)

This is the benchmark-ips report I have been using while working on this:

require 'benchmark/ips'

Time.zone = 'Eastern Time (US & Canada)'

Benchmark.ips do |x|
  x.report('Time.now') {
    Time.now
  }

  x.report('Time.zone.now') {
    Time.zone.now
  }

  x.compare!
end

cc @amatsuda
cc performance folks @tenderlove and @schneems

Pretty... pretty... pretty good.

@KevinBongart

View changes

Show outdated Hide outdated activesupport/lib/active_support/time_with_zone.rb
@natematykiewicz

View changes

Show outdated Hide outdated activesupport/lib/active_support/time_with_zone.rb
Speed up Time.zone.now
@amatsuda, during his RailsConf talk this past year, presented a
benchmark that showed `Time.zone.now` (an Active Support joint)
performing 24.97x slower than Ruby's `Time.now`. Rails master appears to
be a _bit_ faster than that, currently clocking in at 18.25x slower than
`Time.now`. Here's the exact benchmark data for that:

```
Warming up --------------------------------------
            Time.now   127.923k i/100ms
       Time.zone.now    10.275k i/100ms
Calculating -------------------------------------
            Time.now      1.946M (± 5.9%) i/s -      9.722M in   5.010236s
       Time.zone.now    106.625k (± 4.3%) i/s -    534.300k in   5.020343s

Comparison:
            Time.now:  1946220.1 i/s
       Time.zone.now:   106625.5 i/s - 18.25x slower
```

What if I told you we could make `Time.zone.now` _even_ faster? Well,
that's exactly what this patch accomplishes. When creating `ActiveSupport::TimeWithZone`
objects, we try to convert the provided time to be in a UTC format. All
this patch does is, in the method where we convert a provided time to
UTC, check if the provided time is already UTC, and is a `Time` object
and then return early if that is the case, This sidesteps having to continue on,
and create a new `Time` object from scratch. Here's the exact benchmark
data for my patch:

```
Warming up --------------------------------------
            Time.now   124.136k i/100ms
       Time.zone.now    26.260k i/100ms
Calculating -------------------------------------
            Time.now      1.894M (± 6.4%) i/s -      9.434M in   5.000153s
       Time.zone.now    301.654k (± 4.3%) i/s -      1.523M in   5.058328s

Comparison:
            Time.now:  1893958.0 i/s
       Time.zone.now:   301653.7 i/s - 6.28x slower
```

With this patch, we go from `Time.zone.now` being 18.25x slower than
`Time.now` to only being 6.28x slower than `Time.now`. I'd obviously love some
verification on this patch, since these numbers sound pretty interesting... :)

This is the benchmark-ips report I have been using while working on this:

```ruby
require 'benchmark/ips'

Time.zone = 'Eastern Time (US & Canada)'

Benchmark.ips do |x|
  x.report('Time.now') {
    Time.now
  }

  x.report('Time.zone.now') {
    Time.zone.now
  }

  x.compare!
end
```

cc @amatsuda
cc performance folks @tenderlove and @schneems

![Pretty... pretty... pretty good.](https://media.giphy.com/media/bWeR8tA1QV4cM/giphy.gif)
@maclover7

This comment has been minimized.

Show comment
Hide comment
@maclover7
Member

maclover7 commented Oct 2, 2016

@matthewd matthewd merged commit 0464b72 into rails:master Oct 5, 2016

2 checks passed

codeclimate Code Climate didn't find any new or fixed issues.
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

@maclover7 maclover7 deleted the maclover7:jm-speed-up-time branch Oct 5, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment