-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
AppDomain.MonitoringSurvivedMemorySize incorrect in .NET 5.0 #45446
Comments
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label. |
Tagging subscribers to this area: @dotnet/gc Issue DetailsWhile trying to add a new feature to BDN to measure survived memory (dotnet/BenchmarkDotNet#1596), I found that .NET Core 3.1 and .NET 5.0 were reporting unexpected values. I made a separate application to test whether the measurements I'm making are even accurate separate from all other BDN code. I found that it seems to be accurate in .NET Core 3.1, but it's off in .NET 5.0. Console prints:
With this code:
[Edit] This was ran with Visual Studio 16.8.2 on Windows 7 SP1 on AMD Phenom II x6. Also, the results above were from running in DEBUG mode directly in Visual Studio. After building in RELEASE configuration and running it separately, I got these results (different, but still wrong):
|
I actually tried running that test again, and kept getting different results. So I rewrote the code to do many iterations to try to find any anomalies, and I ran it in different runtimes.
|
Interestingly, I found similar issues with regards to measuring allocations in both Core 3.1 and 5.0. See dotnet/BenchmarkDotNet#1543
|
Closing since by .NET 6.0 Preview 6, this issue doesn't reproduce anymore. |
@ivdiazsa I just tried this code again running on
[Edit] It looks like the allocated memory was fixed, but the survived memory is still broken. |
@ivdiazsa I'm still seeing this in |
It would help if you provided more specifications from your current environment. It does not reproduce on our side anymore. |
Visual Studio: 16.11.0 Any other info you need? |
Moving to .net 7, since this appears to be on win7 only? @timcassell are you able to repro this on win10? |
Hi @mangod9, yes I am repro'ing on win10. .Net 6.0.100-rc.1.21458.32 Also for clarity, I am running the code in this comment for measuring survived memory (not allocated). I also tried with Visual Studio 2022 (17.0.0 Preview 4.0), and saw even more unexpected survived measurements, some even negative (though the negatives haven't shown when running standalone exe, only when run in VS)!
|
I've been running this for 15 mins and could not repro at all. @cshung could you please see if you can repro this? I used the test from @timcassell's latest iteration. the test is very straightforward so it's puzzling why the results can be so volatile. |
I should mention that I ran this with corerun, not in VS. running in VS may not make it so straightforward... |
I tried build from command line
|
okie...I'm not sure if @cshung got a chance to look at this. I just took a brief look. I can repro this (I only ever see the 40 bytes difference but the way to debug this would be the same). what I did was I just turned on the gc internal logging (dprintf's) that logged the current SOH and UOH allocated bytes in
then I have the test break into the debugger when it ever detects a difference between before and after. so when it broke I saw that there's a 40 byte difference in SOH alloc bytes so I looked at the last object that got allocated at the end of the ephemeral seg and found the root of it -
this looks like something that gets allocated by the loader allocator stuff. |
(of course you don't need to use dprintf... could just look at the last object(s) allocated) |
By implementing a ICorProfiler implementation and subscribe to the First, note that the implementation of There are just so many stacks that I have a hard time believing these are all the cases, I need to come up with a way to summarize these stacks. Suffice to say that we did allocate, and therefore we observe the survived bytes changes. |
I'm closing this as we established that there was survived bytes. please let me know if you disagree. |
@Maoni0 Huh? Of course I disagree. The API is useless if I can't rely on it to tell me the accurate survived bytes of user code, and even more so if it potentially changes every time it's called when nothing else has changed in user code. The contract is broken. |
I am writing this to do these three things: (1) Correct my previous mistake (1) Earlier, when I said this
This is not entirely accurate, allocations does not necessarily mean survival. I need to make sure the allocation did survive before I conclude earlier. (2) Between the time we printed "Searching for abnormal survived memory..." and "Abnormal survived memory found in {abnormalCount} out of {iterations} iterations.", we did a lot of allocations. Here is a call stack for the important allocations that does survive only on .NET 6 or below:
I understand the stack is cryptic, so here is a hopefully simple explanation of what is going on. At the bottom of the stack, In .NET 7, #67160 changed the JIT inlining tracking map so that the tracking data is no longer allocated on the GC heap, so this allocation on the GC heap is not happening anymore.
(3) The contract of the method
It says nothing about whether or not the bytes are allocated by the user code or not. So there isn't a contract violation per se. That being said, I understand it can be inconvenient for benchmark.net to consume this API. Fortunately, the survival is gone in .NET 7. So I would recommend using this API for .NET 7+. @timcassell, if you observe the value still changes after #67160, feel free to let us know and we will deal with that on a case-by-case basis depending on what else is allocated on the GC heap. (*) For the record, here are some unimportant allocations that does not survive.
Printing out the interpolated string leads to some allocation due to When we perform a Since none of these survives, so they are fine and does not contribute to the |
@cshung Thank you for the detailed information. I have tested again on the latest .Net 7 preview and can confirm I no longer see abnormal survived bytes. |
While trying to add a new feature to BDN to measure survived memory (dotnet/BenchmarkDotNet#1596), I found that .NET Core 3.1 and .NET 5.0 were reporting unexpected values. I made a separate application to test whether the measurements I'm making are even accurate separate from all other BDN code. I found that it seems to be accurate in .NET Core 3.1, but it's off in .NET 5.0.
Console prints:
With this code:
[Edit] This was ran with Visual Studio 16.8.2 on Windows 7 SP1 on AMD Phenom II x6.
Also, the results above were from running in DEBUG mode directly in Visual Studio. After building in RELEASE configuration and running it separately, I got these results (different, but still wrong):
The text was updated successfully, but these errors were encountered: