-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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 invalidations in deserialization #41872
Reduce invalidations in deserialization #41872
Conversation
I think it should be fine, but I haven't tested. Between getting a review (this LGTM, but it would be better if @vtjnash has time to comment) and merging, I can build this locally and test it. |
I believe that you cannot do this order, since the state of the invalidation trees is not quite consistent yet, so we might actually end up deleting many methods whose only fault was being inserted in an unpredictable order. I think we instead need to add to the list of methods here for post-processing the internal ones, with an empty array for the (flattened) edges. |
Okay... That goes way beyond my current understanding of the deserialization process and I'm not sure digging deeper into that is a worthwhile investment of my time - looking at stuff where (I at least think that) I know what I'm doing sounds more efficient. |
In JuliaLang#38983 and JuliaLang#41872, it was discovered that only CodeInstances with external backedges get validated after deserialization. This adds a "second chance" for each CodeInstance: it validates any that have neither been validated nor invalidated by the end of deserialization. Closes JuliaLang#41872
In JuliaLang#38983 and JuliaLang#41872, it was discovered that only CodeInstances with external backedges get validated after deserialization. This adds a "second chance" for each CodeInstance: it validates any that have neither been validated nor invalidated by the end of deserialization. Closes JuliaLang#41872
This is more of an issue than a PR perhaps, but I had to try to fix it to get a handle on it. So let me take my attempt and turn it into a PR for the sake of discussion.
So here is the issue (ref. #38983 (comment)): We start from a package with the followeing (pathological) content:
Now, in a fresh session (after
using Foo
once in another session to trigger precompilation):So why does inference basically start over here? Here is my analysis:
Upon deserialization, we first mark all
CodeInstance
s invalid. Then we go and check all methods whether they have been invalidated by external callees. If not, we mark them valid. But we only do this for methods which actually have external callees. In this case, that means we checkfoo(::Int)
and find it is still valid. But we never checkfoo()
, leaving it marked as invalid. And as it is never actually invalidated by anything,@snoopr
cannot report it. But then it needs to be re-inferred when called, which thanks to constant propagation and omission of the inlinedhcat(::Int)
method from the cache becomes relatively heavy.So what I try to achieve with this change is to reverse that logic and first consider everything valid until it gets detected as invalidated. For methods with external callees this is pretty straight-forward, but we need to consider that if one of these gets invalidated, we have to propagate the invalidation to its callers (which might not have external callees themselves). Luckily, we have the backedges recorded to do just this. So with this patch I get the expected:
Invalidation still seems to be working:
@vtjnash is that reasoning valid and if so, does the implementation strategy look reasonable? Also cc @timholy.
One thing I should add is that the effect on real-world packages seems to be rather limited. But would still be nice to have this sorted out, if only too avoid distraction when trying to figure out why one's precompile statements don't have the desired effect---which is what brought me here...