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 recursion guard #8
Conversation
A simple benchmarking script shows IceNine.deep_freeze running ~30x faster on nested Hashes/Arrays: https://gist.github.com/misfo/6600943
By the way, I love the library. We actually found (and fixed) a bug in another library because we were deep freezing our data |
@misfo thanks for this, I'll check it out in more detail. At first glance, my largest concern is that |
But Couldn't we just make |
@misfo I think you're right about that. I see the change you made and it looks good. Would you mind adding a In general I really like this approach. I don't mind that we're passing a variable recursively since the interface change won't break any existing usage. I'm going to do a pass over the code and make some suggestions, but otherwise I think this will be merged in very shortly. One thing that came to mind is if |
Also, I should mention it's conventional wisdom in the ruby community that Obviously, when n is large If an def initialize
@object_ids = []
end
# ...
def guard(caller_object_id)
return if @object_ids.include?(caller_object_id)
begin
@object_ids << caller_object_id
yield
rescue
@object_ids.pop
end
end I suspect this will be faster than |
@misfo I ran into the same performance problem when deep freezing large parsed array/hash primitive trees I parse from JSON in my esearch library. And I ended up into using |
@misfo ok, this PR looks good. My only request before merging it is that you merge (current) master in and run |
…-up-recursion-guard
This prevents some possible revisiting of object (IDs) and kills a TooManyStatements warning
Alrighty. I addressed a few of the things, but I still have some mutants to kill... |
I addressed all the
|
About the most efficient data structure for the set of object IDs, the Google showed me that somebody already dug into that question in the java world. So it could be that using an Anyways, it might be worth looking into as a separate ticket |
@misfo I think you're right. I've done some research too and it led me to a bitset as well, but given that your general approach is an improvement I'm no going to push further in this direction. I may open another issue for further research later, but for now I'm happy with the significant improvement this brings. I'll look at those remaining mutations and see if I can make some suggestions and/or fix them. |
@misfo thanks so much for this, I fixed the remaining mutations as well as refactored a few of the tests (in ways that I probably should've done earlier). I decided to just use a plain |
@misfo btw, I just released ice_nine 0.10.0 to rubygems with these changes: https://rubygems.org/gems/ice_nine/versions/0.10.0 Thanks again! |
Cool. Thanks! Just curious: was there a fix for the Sent from my phone
|
AFAIK refactoring the code into a form the mutations do not occur. You dont have to kill mutations from specs. |
...to be more specific, you don't always have to kill mutations via specs. Sometimes alive mutation leads to simplifying code. |
@dkubb Thanks for releasing the new version. We updated the gem in our app and here are the elapsed times for one of the affected parts of our app (the time it was taking to Before the update:
After updating to 0.10.0:
|
@mbj actually I found that a few mutations are still alive under ruby 2.0.0, but not 1.9.3. I'm fairly sure that the remaining mutations are actually the result of a bug in mutant, but I need to isolate it. If you're curious run ice_nine edge with mutant under both rubies and note the difference. |
@misfo wow! that's quite a difference. nice work! |
@misfo holy crap, nice! |
@misfo wow nice work there man, thanks for that. a lot of our libs will benefit from this patch ❤️ |
@mbj I saw the difference with the rake task, which I think adds |
@dkubb You saw that zillions "Zombifiying $rb_file" messages? On Thu, Sep 19, 2013 at 09:33:05AM -0700, Dan Kubb wrote:
Markus Schirp Phone: +49 201 / 360 379 14 Altendorferstrasse 44 |
A simple benchmarking script shows
IceNine.deep_freeze
running ~30x faster on nested Hashes/Arrays.We ran into some performance issues at work with using
IceNine.deep_freeze
andinclude Adamantium
, so we had to switch to using shallow.freeze
s andinclude Adamantium::Flat
. I did some profiling ondeep_freeze
and it looked like the recursion guard code was taking up most of the time. In particular the call toKernal#caller
was taking up a big percentage of the running time.RecursionGuard.guarded_objects
was taking a smaller, but significant, percentage as well.This commit explicitly passes the recursion guarding down the call stack. The code is, admittedly, not as clean as it was before, but it makes for acceptable performance of deep freezes on large data structures (in our case, the large data structures were deserialized responses from a JSON API).
The commit does add an additional
recursion_guard
argument to a few public methods. If you don't want those optional arguments as part of the public API, I could probably refactor those out somehow...