How to get .NET to uncommit unused RAM?

2019-04-24 17:35发布

Here are the stats for my program after it used memory extremely intensively, consuming 6 GB at its peak, but then saving everything to disk and leaving very little in scope:

Screenshot

Observe that almost everything has gone out of scope and has been garbage collected - the heap sizes are tiny. And yet, .NET keeps 181 MB committed.

I don't mind the reserved bytes, since that only consumes address space. But the committed memory is annoying – even if it only resides in the page file, it's still quite a lot.

1条回答
叛逆
2楼-- · 2019-04-24 18:14

According to CLR Inside Out - Large Object Heap Uncovered the CLR decommits un-used committed memory during a Gen 2 garbage collection.

This means that you can either wait for a Gen 2 garbage collection to happen on its own or you can force one using GC.Collect() - you really need to know what you are doing if you choose this route however as it messes with the garbage collectors standard garbage collection cycles which can really mess with performance:

  • A full garbage collection is slow so you really don't want to do this too often
  • Triggering garbage collections more frequently than the standard schedule will promote additional objects to higher generations meaning they might not be collected as soon as they would normally be

As far as I am aware (from my fairly limited research) the CLR won't release committed memory in other situations.

You should also consider whether or not this is actually a problem:

  • If your process is going to immediately go on to perform additional memory-intensive processing then it will need that memory again fairly soon and so there isn't a huge amount of benefit of decommitting that memory anyway
  • If you process is done and will terminate shortly then the memory will be decommited anyway
  • There isn't necessarily going to be a large disadvantage to having that much memory committed anyway - yes it means that the memory has a backing store allocated, however if the system is under memory pressure then that backing store is likely to be a page file anyway.

Update: Advanced .NET Debugging: Managed Heap and Garbage Collection appears to back up the hypothesis that memory is only uncommitted during a gen 2 / full collection:

When objects in generation 2 are collected, the CLR heap manager decommits memory in the segments, and when a segment is no longer needed, it is entirely freed.

查看更多
登录 后发表回答