I’ve been trying to track down a seeming memory leak in “untracked memory” in Caves of Qud.
After many days, I’ve finally narrowed down the repeatable cause of this untracked memory, and it seems to be completely managed.
I’m using a specific save game reproduction (that is very very unusually large) and doing sorts on hundreds of megabytes of strings. With the only difference in the code pictured below, I repeatedly generated hundreds of megabytes of “untracked” memory?
Is it possible that a ton of allocations on a non-ui thread would cause managed memory to silently blow some kind of internal memory profiler buffers become and “untracked”? That’s what this smells like to me.
It may simply be StringBuilders. Running this code over and over again explodes “Untracked” memory

This issue reproduces in a naked project, I’ve submitted the reproduction as IN-76639
Hey,
Thanks for the bug report. I’ve very recently found out that, unless I misread the code (and I still need to dig deeper and attempt to fix that gap in reporting), the managed VM code never really returns pages used for the managed heap to the OS. It unmaps them and immediately remapps them for later usage. Those remapped pages are currently untracked.
So what bloats up your untracked memory might very well be managed heap fragmentation.
Hah, I don’t envy having to untangle that nest.
In my view this is a pretty serious issue. This thread is the end result of almost a week of trying to figure out what was causing “untracked” memory bloat, and all the documentation, on-screen guidance and forums threads claim it’s probably native plugin allocations, or perhaps texture or clip leaks, and so it was quite shocking to find it was StringBuilders, and I only discovered it after starting to simply exhaustively cut away parts of the application until I found the issue.
Even now it will be harder to clean up than it might be if StringBuilder allocations aren’t fully showing in the memory profiler. Though now vastly easier since I’ve identified the culprit!
The memory profiler is a great tool, definitely 100,000x easier than the old days when I couldn’t get ANY view on non-main-thread memory at all. 
3 Likes
Glad to hear that it helps!
And yeah, I suspect the only thing I can fix here is visibility into where that memory belongs to, but trying to combat managed fragmentation is an arcane art… The easiest way to deal with it imo is to … Not use managed memory. I.e. move that sorting stuff to Native Containers
Yeah, honestly probably doesn’t need extensive fixing, just a note on the untracked memory UI in the bullet points of what it could be saying “*might be stringbuilder!!” would have been sufficient for me to figure out my issue. (And anything else that’s currently being sneakily allocated by unity in untracked)
Though in an ideal world I think those allocations would show up under native.
Not just stringbuilder though. Any managed memory that allocated more than half a page (assuming 4KB page size >2KB) of memory where that paged is now no longer used and doesn’t fit the next bigger than page size allocation due to fragmentation and therefore continues to fragment the heap, triggers GC and eventually unloads these pages towards untracked.
Stringbuilder doesn’t allocate native memory. It’s all managed.
Like your usage of Linq could just as well be the reason. A mixture of small allocations for delegates and big allocations for new array creations and boom: fragmentation.
Ah, I see, so the hypothesis is it’s acting almost purely a proxy for managed heap fragmentation in this case.
1 Like