3

We've had a long term issue with one of our products consuming GBs of memory when in production. We often get low memory warnings on the server, and finally today I finally had chance to sit down with a memory profiler and see where the memory is going. In development, with the same database and config, the application's private working set is 450MB. On the production server, the amount of memory allocated to that process is 3.7GB.

Using Ants Memory Profiler, I determined that 2.906GB of that memory is being allocated to the Generation 1 Heap:

Graph

This amount of memory does get utilised on application start as we load a lot of data from the database to generate some caches. However, it all gets cleaned up, as you can see by the fact all of the data in the graph above is allocated, but not used. Here's the complete overview:

Memory Summary

As you can see, the LOH is pretty much empty and not fragmented. I know that the LOH doesn't get compacted, unless you specifically set CompactOnce to the applicable GCSettings enum. But I was under the impression that the Generation 0-2 heaps do get compacted and should get free space released? Or does the CLR just assume that because that much memory was consumed once, that the application should keep addressing that memory in case it needs that much again?

To me, our app should only be consuming about 600-700MB (most of which is the CLR). So:

  1. Does anyone know why this free space is remaining allocated and only on a production server and not on development laptops?
  2. Is there any way to manually release this free memory from the gen 1 heap?
djdd87
  • 67,346
  • 27
  • 156
  • 195
  • Is the production build a `release` build, and if you try to reproduce on the development machine, do you then also use a `release` build? – Maarten Jan 07 '16 at 15:44
  • @Maarten Yes they're both in release build. I've even used the same published deployment files we generate for the releases. – djdd87 Jan 07 '16 at 16:11
  • Are you using server or workstation GC on the production server? What about on the dev laptop? Which version of .NET are you using?. In general, what you see is typical because the GC will allocate enough memory to accommodate all of the objects allocated at startup and then when they are deallcoated, the memory itself is not freed. The GC keeps the allocated memory to improve performance the next time you allocate that many objects. However, when system memory gets low, it releases most of this unused memory. – Hadi Brais Jan 07 '16 at 17:37
  • @HadiBrais That's what I expected, thanks. However, to answer your questions they're both using gc server (gcServer enabled="true") and the .Net version is 4.5.1. Do you have any links to anywhere stating that free memory is released from the generation 0/1/2 heaps when system memory gets low? – djdd87 Jan 08 '16 at 08:14
  • @HadiBrais Could it be that memory is just being released on development machines? We've got 8GB of RAM, the server has 128GB. With SQL instances/Visual Studio/other dev tools running, I appear to be using about 5.7GB. Add on that 3GB of cache loading and it will no doubt force all that free to be memory released. – djdd87 Jan 08 '16 at 08:38
  • 2
    @GenericTypeTea The answer is clear now. This behavior is documented [here](http://www.asp.net/aspnet/overview/aspnet-and-visual-studio-2012/whats-new#_Toc_perf_5) and [here](https://msdn.microsoft.com/en-us/library/bb384209%28v=vs.110%29.aspx). On your dev machine, the system became very low on memory forcing the GC to release its unused memory. This didn't happen on the server because it has 128GB of memory. – Hadi Brais Jan 08 '16 at 09:39
  • 1
    The first link from @HadiBrais no longer works, but can be found on the Web Archive: https://web.archive.org/web/20160621111228/http://www.asp.net/aspnet/overview/aspnet-and-visual-studio-2012/whats-new#_Toc_perf_5. – Bouke Mar 05 '21 at 19:33

0 Answers0