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
GC does not clean up memory allocated in same method #11152
Comments
This is same issue as: https://github.com/dotnet/coreclr/issues/15207 The JIT can produce temporary local variables. These temporary local variables are outside your control and they may result into the reference lifetime getting extended. The likelihood of this happening is much higher with optimizations off. This issue can happen with optimizations on as well for more complex methods. |
A slightly adjusted version is here: This simulates the original issue we had, a long running loop that holds state and clears it. It doesn't reproduce in release, but I'm worried if something like this can happen on release? Also, WinDBG gives inconsistent results: https://gist.github.com/ayende/75fd760a83252730786b5feb8faf887a I wonder if a good choice for long running loops would be to do the inner loop work in its own method, to avoid this ? |
A separate method would fix that reliably only if it is marked as non-inlineable. |
I don't think we're ready to sign the JIT up to guarantee lifetimes match their lexical scopes. In fact, we're constantly "fixing" test cases that make the same assumption about lifetimes as above. In theory, we might consider addressing particularly egregious examples that were hitting in real world code in release builds, but even then the workaround of creating a no-inilne helper method would be our recommendation most of the time. @dotnet/jit-contrib Feel free to re-open if you see anything actionable here. |
This has been discussed elsewhere, but another point to make is that the spec is careful to make few guarantees about when finalizers are called, specifically to provide flexibility to runtimes and code generators with regard to optimization and reporting. See in particular I.8.9.6.7 - "Since programmers might depend on finalizers to be called, the CLI should make every effort, before it shuts down, to ensure that finalizers are called" (implying that even calling them before shutdown is a "best effort" requirement). |
This part of the spec is outdated. .NET Core does not make effort to call finalizers during shutdown. |
This only happens in debug builds, when using release builds, the code below works properly.
During debug build, even though we have cleared the reference to
b
, the GC still maintains that it is tracked.In fact, if we break into this using WinDBG, we can see that there is such a root holding the value, but I can't figure out where it is coming from.
I'm aware of the release / debug GC behaviors with respect to not eagerly clearing out variables that are still in scope, but in this case, we are explicitly setting the value to null and invoking the GC to clean things up.
This actually showed up for us when we noticed high memory utilization in a scenario where it shouldn't. This was using a debug build, and while we cleared up the field that was holding the value, we had the same experience. Under debug, there is something else that holds a reference to the value.
The text was updated successfully, but these errors were encountered: