Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't .NET release unused memory back to OS when physical >95%?

We are testing a 4-process WCF IIS application (x3 release versions) for memory stability (leaks) by simply pinging it every ~1s as a Load Balancer might. It runs fine for >12hours if nothing else is running on the server.

However if we purposely reduce the total available memory (fixing the page, reduce physical memory, launch other apps) and push the physical memory usage to 97% and leave it there for 5 minutes or more, oftentimes Windows will sense the condition and shutdown one of the processes. Note it also fails if the total memory is pushed to 97% (by using a fixed page file).

However, analyzing the memory footprint of one of the surviving processes using the RedGate tool, shows this:

RedGate Summary Tab

Since the requests are just a steady ping, there seems to be no practical reason for .NET to hold the 269MB free memory when the server is starved. About 50% of the IIS Processes appear to be in this state (~1.8GB).

The App is compiled against .NET 4.0, gcServer true. IIS Gate checking was set to 0% (minFreeMemoryPercentageToActivateService="0") although we would probably set it to 2% in production.

The Server is 2008 R2, ~4GB physical 4GB fixed page, was tested with 4.0 and then 4.5.1 (didn't matter).

There is an answer to a similar question by @atanamir claiming:

".NET will free its heap back to the OS once you're running low on physical memory."

Anyone know of any reference for that claim? Could it be version specific?

Refs:

  • .NET Free memory usage (how to prevent overallocation / release memory to the OS)
  • When is memory, allocated by .NET process, released back to Windows
like image 727
crokusek Avatar asked Feb 19 '15 18:02

crokusek


1 Answers

This is not exactly an answer to the question you asked (why) but it should be a way to achieve what you’re trying to do.

There is something new with .NET Framework 4.5 - source

Once a site is running, its use of the garbage-collector (GC) heap can be a significant factor in its memory consumption. Like any garbage collector, the .NET Framework GC makes tradeoffs between CPU time (frequency and significance of collections) and memory consumption (extra space that is used for new, freed, or free-able objects). For previous releases, we have provided guidance on how to configure the GC to achieve the right balance. For the .NET Framework 4.5, instead of multiple standalone settings, a workload-defined configuration setting is available that enables all of the previously recommended GC settings as well as new tuning that delivers additional performance for the per-site working set. For example, there is no need to set gcServer, gcConcurrent, etc.

Also here they state:

Tuning GC for high-density Web hosting: GC can impact a site’s memory consumption, but it can be tuned to enable better performance. You can tune or configure GC for better CPU performance (slow down frequency of collections) or lower memory consumption (that is, more frequent collections to free up memory sooner) […] in order to achieve smaller memory consumption (working set) per site

To enable GC memory tuning, add the following setting to the Windows\Microsoft.NET\Framework\v4.0.30319\aspnet.config file and Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet.config file:

<configuration>
<!-- ... -->
<runtime>
<performanceScenario value="HighDensityWebHosting"  />
<!-- ... -->  

Basically, based on the tests I made, I saw that it will consume more CPU, less memory and make the GC to be more aggressive in terms of clean up and memory release process. We tested this setting within our infrastructure (IIS 7.5, new 4.5 framework) and the results were impressive. High memory usage leading to out of memory exceptions are no more an issue.

Hope it helps.

like image 128
Cedricc Avatar answered Nov 14 '22 20:11

Cedricc