服务器模式 GC 似乎永远不会收集 Gen 0 Heap [英] Server mode GC seems to never collect Gen 0 Heap

查看:28
本文介绍了服务器模式 GC 似乎永远不会收集 Gen 0 Heap的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

澄清问题(tl;dr)

在阅读和分析下面涵盖的所有结果后,问题似乎归结为 GC 在服务器模式下没有为我们的应用程序收集 Gen 0 堆,一旦切换到工作站模式,问题就会消失.

原始问题和详细信息

我的问题有点相关: 更多相关的 SO 问题,但他的发现是这种内存使用不是问题,而在我的情况下,该服务实际上需要每天至少手动重新启动一次.

我还找到了这篇文章 关于这个问题有以下说法(这似乎几乎完美地描述了正在发生的事情:

<块引用>

在 64 位系统上,第 0 代可能有更多的对象,尤其是当您使用服务器垃圾收集而不是工作站垃圾收集时.这是因为在这些环境中触发第 0 代垃圾收集的阈值更高,并且第 0 代垃圾收集可以变得更大.当应用程序在触发垃圾回收之前分配更多内存时,性能会得到提高.

尽管问题仍然存在,在服务器模式下,第 0 代堆似乎从未被收集,而不是经常被收集.

解决方案

经过大量研究、阅读和分析,我已经能够证明我们的 IIS 内存使用实际上在标准范围内;这是使用 SysInternals Test Limit 实用程序来将服务器的物理内存使用量推到接近最大值,一旦完成,我们所有的应用程序都会释放它们的内存.

我们的测试环境中确实存在某种内存问题,我需要对其进行调查,但在这一点上,我认为我可以自信地说这完全不相关.

故事的寓意是不要假设报告的问题原因是正确的.

Clarified question (tl;dr)

After reading and profiling with all the results covered below, the problem seems to boil down to the GC not collecting Gen 0 Heap for our applications when in Server mode, as soon as its changed to Workstation mode the problem goes away.

Original question and details

My question is somewhat related to:This question and this question.

We recently ran into what seemed to be a memory leak in our .NET applications on our test environments, the worker processes would climb to around 450MB usage either quickly when under load or gradually when under no load.

The problem could not be replicated on our development environments, the primary difference being that the dev environments are physical servers whereas the test environments are virtualized and controlled by Puppet (apart from that I do not have much knowledge of the environments themselves).

In order to hopefully see what objects were responsible for taking up all that memory I ran Ants Memory Profiler on the test server, I found that all of that memory was remaining as unused and was never being released.

While researching what could cause this I came across this forum post which in turn lead me to this article.

I ended up trying the configuration it recommends, to put the GC into workstation mode:

<configuration>
  <runtime>
    <gcServer enabled="false"/>
    <gcConcurrent enabled="false"/>
  </runtime>
</configuration>

After running iisreset and re running my memory profiling the issue was completely gone, which is great but still doesn't really explain what was happening in the first place.

I did do some more reading and found this SO question, which leads me to believe that this configuration change may end up being detrimental to the throughput of our applications.

So my question is: What would cause an IIS worker process to accumulate a large amount of unused memory that never gets garbage collected?

Edit: To clarify my question a bit more, I believe we have proven that the code is not responsible for this, as the exact same code does not experience this issue on the dev environment.

Here are the screenshots I took of my memory profiling before and after the configuration change, there isn't a lot of information here but the graph does show the memory trend nicely.

Edit 2: Here are the server specs from what I could gather, I can possibly get more will just take time.

Dev Environment: Physical Machine CPU: Single core Memory: 6GB

Test Environment: Virtual Machine CPU: 4 Logical threads (I cannot comment on CPU count) Memory: 8GB

The only difference in the Machine.Config files is that the dev environment is adding "Microsoft.VisualStudio.Diagnostics.ServiceModelSink.Behavior" to both endpoint and service behaviours.

And the test environment currently has the GC settings previously mentioned in the aspnet.config file.

Edit 3: Did some more profiling and noticed a couple more counters that I could add within Ants, notably I added "Gen 0 heap size" and it looks like this is the source of the issues. With the GC in server mode when I trigger the test I'm using for profiling this line immediately jumps up to ~300MB then comes back down to ~230MB but never goes all the way back down (graph below).

Running the same profiling with the GC in workstation mode sees the Gen 0 heap size have a much smaller initial spike and return back to essentially zero when the requests have finished (graph below).

Doing some more searching on this lead me to another much more related SO question, however his findings were that this memory usage was a non issue, whereas in my case the service actually needs to be manually restarted at least once a day.

I also found this article that had the following to say on the issue (which seems to describe what is happening almost perfectly:

Generation 0 is likely to have a larger number of objects on a 64-bit system, especially when you use server garbage collection instead of workstation garbage collection. This is because the threshold to trigger a generation 0 garbage collection is higher in these environments, and generation 0 collections can get much bigger. Performance is improved when an application allocates more memory before a garbage collection is triggered.

Though the problem still remains that in Server mode the Generation 0 heap is seemingly never collected as opposed to just not as often.

解决方案

After much research, reading, and profiling I have been able to prove that our IIS memory usage is actually within the standard; this was done using the SysInternals Test Limit utility to push the server's physical memory usage to near max, once this was done all of our applications released their memory.

We do still have some kind of memory issue in our test environment that I need to investigate but at this point I think I can confidently say that this is entirely unrelated.

Moral of the story is to not assume that the cause reported with the issue is correct.

这篇关于服务器模式 GC 似乎永远不会收集 Gen 0 Heap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆