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

Reduce memory by not duplicating an argument #404

Merged

Conversation

technicalpickles
Copy link
Contributor

I spotted this in a memory_profiler report for some of my app's specs. timecop was showing up in the list of gems with the most allocated memory.

This dup appears unnecessary. The code I can see isn't making modifications to the object, and I would expect at to return an new object anyways.

memory_profiler before:

allocated memory by location
-----------------------------------
...
49_836_480  /Users/josh.nichols/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/timecop-0.9.6/lib/timecop/time_stack_item.rb:59
...

allocated objects by location
-----------------------------------
...
934_434  /Users/josh.nichols/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/timecop-0.9.6/lib/timecop/time_stack_item.rb:59
...

memory_profiler after:

allocated memory by location
-----------------------------------
...
26_997_696  /Users/josh.nichols/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/timecop-0.9.6/lib/timecop/time_extensions.rb:79
...

allocated objects by location
-----------------------------------
662_346  /Users/josh.nichols/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/timecop-0.9.6/lib/timecop/time_stack_item.rb:59

This decreased memory allocated in my tests by 45%, and objects allocated by 29%.

I spotted this in a memory_profiler report for some of my app's specs.
timecop was showing up in the list of gems with the most allocated memory.

This dup appears unnecessary. The code I can see isn't making
modifications to the object, and I would expect `at` to return an new
object anyways.

memory_profiler before:

    allocated memory by location
    -----------------------------------
    ...
    49_836_480  /Users/josh.nichols/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/timecop-0.9.6/lib/timecop/time_stack_item.rb:59
    ...

    allocated objects by location
    -----------------------------------
    ...
    934_434  /Users/josh.nichols/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/timecop-0.9.6/lib/timecop/time_stack_item.rb:59
    ...

memory_profiler after:

    allocated memory by location
    -----------------------------------
    ...
    26_997_696  /Users/josh.nichols/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/timecop-0.9.6/lib/timecop/time_extensions.rb:79
    ...

    allocated objects by location
    -----------------------------------
    662_346  /Users/josh.nichols/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/timecop-0.9.6/lib/timecop/time_stack_item.rb:59

This decreased memory allocated in my tests by 45%, and objects
allocated by 29%.
@@ -56,7 +56,7 @@ def scaling_factor

def time(time_klass = Time) #:nodoc:
if @time.respond_to?(:in_time_zone)
time = time_klass.at(@time.dup.localtime)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😮

@joshuacronemeyer
Copy link
Collaborator

@technicalpickles Thanks for the thoughtful PR. I've reviewed it and will merge it now.

It's interesting, I was curious why we had the dup in the first place and I traced it back to this commit 27dc330 And that commit is from this PR #107

It looks like that dup is no longer necessary since we don't call the UTC method anymore... So since this commit 18474ab the dup isn't giving us anything.

👏

@joshuacronemeyer joshuacronemeyer merged commit 0ad9c66 into travisjeffery:master Aug 10, 2023
11 checks passed
@technicalpickles technicalpickles deleted the dont-dup-time branch August 10, 2023 22:48
@technicalpickles
Copy link
Contributor Author

@joshuacronemeyer thanks! I started looking at the git history, but didn't get back far enough where it was first used (rather than just moving it around)

Hm, I'm looking more closely at localtime, it's calling utc.utc.getlocal(utc_offset), and utc does:

  @utc ||= incorporate_utc_offset(@time, -utc_offset)

The test added in #107 is still around, and passed though, so it must have had different behavior previously.

@joshuacronemeyer
Copy link
Collaborator

Hmm. That's interesting. Yea hopefully we're not asking for trouble here, but I also am looking to that test to tell me that we're in the clear on this. One interesting thing is that it has to be a difference in the way we call it, not the behavior of ruby because our build runs a bunch of really old rubies.

@citystar
Copy link

@joshuacronemeyer Hi, this fix changes @time's timezone. Is it expected? Do we have an option to avoid it?

irb(main):001:0> t1 = Time.now.utc
=> 2023-08-14 01:47:16.918427 UTC
irb(main):002:0> t2 = Time.now.utc
=> 2023-08-14 01:47:21.596669 UTC
irb(main):003:0> t1.localtime
=> 2023-08-14 10:47:16.918427 +0900
irb(main):004:0> t2.dup.localtime
=> 2023-08-14 10:47:21.596669 +0900
irb(main):005:0> t1
=> 2023-08-14 10:47:16.918427 +0900
irb(main):006:0> t2
=> 2023-08-14 01:47:21.596669 UTC

@technicalpickles
Copy link
Contributor Author

@joshuacronemeyer sounds like reverting is called for. I can follow up with another attempt with better tests.

@joshuacronemeyer
Copy link
Collaborator

@nagachika @citystar @technicalpickles i released a new version that reverts this code. Please let me know if the issue is resolved. @citystar I'd really appreciate it if you could provide enough of the code from your failing test for us to reproduce this issue. We have a test for this scenario but apparently it does not work 😿

@joshuacronemeyer
Copy link
Collaborator

@citystar oops. Sorry i see your earlier comment. That is what we need. Thanks again.

@citystar
Copy link

citystar commented Aug 16, 2023

@joshuacronemeyer Thank you for the quick fix. The new version works perfectly at our side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants