-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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
references to interpolated values persist in modules #9375
Comments
I think this is because |
Hmm, this was meant to be a reduced test case. I have a more complex example where this occurs with a type that has fields. |
Here's a larger test case involving Ipopt and JuMP: Run this gist with the following patch to Ipopt.jl
What's a good way to debug this? |
Jeff's tip here is the only way I know. I tried this and it looks like there are some functions that maintain references to the model that are dynamically created in ReverseDiffSparse. A function created here maintains a reference to a |
This is very helpful. I can reorganize ReverseDiffSparse to not embed references to values in function definitions. I don't quite understand the |
The constant table issue may be related to #6597. According to the source, the |
I can work around this behavior if it's decided that this is how the GC needs to work, though it is pretty subtle and surprising. |
@simonster How do I mark a module for collection? This sounds related to a problem that I am having. |
@vchuravy Once there are no longer any references to a module, it should be collected. That part seems to work for me. Defining a module as |
It's nearly impossible to remove all references to a module, since you would need to eliminate any methods it added to other modules and all instances of types defined in that module. Why does your AST contain non-AST things? An closure does not. You would need to eval a function definition AST with an interpolated value in it to get that. |
That's exactly what was done in ReverseDiffSparse, but I can work around it by using closures instead. |
There's actually a pretty significant performance issue here. I've been interpolating functions into ASTs so that type inference works correctly. Moving over to a closure gives me a 40% slowdown in one of my benchmarks. Do I have to eval the generated functions into a new module that I can dispose of later? |
Can you point to the case where this is needed for inference? Can you just add a typeassert, or improve the inference stage to handle your specific case? |
This is buried pretty deep in ReverseDiffSparse. I think the issue is more that using the closure form leads to extra allocations because there are tuples and splatting and runtime dispatch involved. If the function is interpolated into the AST, I'm assuming that Julia is doing something smart and determining which method to call at compile time. If the function is passed in, the dispatch needs to happen at runtime, which is slow in itself and also seemingly triggers more work for the GC because the function is being called as |
I don't mind if this is closed as wontfix. I understand now that values spliced into functions become module variables which won't be gc'd with the function itself. |
improvements have been made here (especially with the anonymous function rewrite) |
The following code:
prints
(It sometimes also segfaults in
uv_write2
, hoping that that's already captured in some issue...)Why doesn't the GC finalize the object when
gc()
is called? If I use a large object like an array instead, I see the expected behavior. I'm guessing that the object seems too small to care about, but this behavior is particularly bad if the object really represents an opaque C struct whose memory the Julia GC isn't aware of.Ref jump-dev/JuMP.jl#330
The text was updated successfully, but these errors were encountered: