【发布时间】:2014-09-24 00:41:16
【问题描述】:
我有一个基于 .NET Framework 4.5 (C#) 构建的后端应用程序(Windows 服务)。该应用程序运行在 Windows Server 2008 R2 服务器上,内存为 64GB。
由于我有依赖关系,我曾经将这个应用程序作为 32 位进程编译和运行(将其编译为 x86),并使用 /LARGEADDRESSAWARE 标志让应用程序在用户空间中使用超过 2GB 的内存。使用此配置,平均内存消耗(根据任务管理器中的“内存(私有工作集)”列)约为 300-400MB。
我需要 LARGEADDRESSAWARE 标志以及将其更改为 64 位的原因是,虽然 300-400MB 是 平均,但有时这个应用程序会做一些涉及加载的事情大量数据进入内存(当你的内存不是很有限时,开发和管理这类东西要容易得多)。
最近(在删除那些 x86 原生依赖项之后),我将应用程序编译更改为“任何 CPU”,所以现在,在生产服务器上,它作为 64 位进程运行。从我进行此更改开始,平均内存消耗(根据任务管理器)达到了新的水平:3-4 GB,而没有其他更改可以解释这种行为变化。
以下是有关当前状态的一些其他事实:
根据“#Bytes in all heaps”计数器,内存总量约为600MB。
在使用 WinDbg+SOS 调试进程时,!dumpheap -stat 显示大约有 250-300MB 空闲,但所有其他对象都远小于进程使用的内存总量。
根据 GC 性能计数器,定期进行 Gen0 收集。事实上,“% Time in GC”计数器表明平均 10-20% 的时间花在 GC 上(考虑到应用程序的性质,这是有道理的 - 大量分配的信息和数据结构用于短时间)。
我在这个应用程序中使用 Server GC。
服务器上没有内存问题。它使用了大约 50-60% 的可用内存 (64GB)。
我的问题:
为什么分配给进程的内存(根据任务管理器)与 CLR 堆的实际大小有很大差异(进程中没有非托管代码可以解释这一点)?
为什么 64 位进程与以 32 位进程运行的相同进程相比占用更多内存?即使考虑到指针的大小是原来的两倍,也有很大的不同。
我可以做些什么来降低内存消耗,或者更好地理解这个问题吗?
谢谢!
【问题讨论】:
-
您推迟处理泄漏问题 far 的时间太长,将忽略位翻转了两次。你不能再翻转它。你必须找到泄漏,它是一个不受管理的泄漏。位图是标准的 gobblers。
-
我观察到 .NET 4 在 ASP.NET 中使用的内存是 .NET 2-3.5 的两倍多。
-
私有工作集不是使用的内存。它是“使用”的内存(对于该词的某些定义)也被分页。使用计数器“私人内存”。对我来说很有意义:内存使用量不适合 2GB,因此您增加了可用内存。现在,如果内存使用量超过 2GB,请不要感到惊讶。事实上,300MB 这个数字从一开始就应该让你怀疑。为什么 2GB 的地址空间不适合 300MB 的内存。
-
为了使我之前的评论具有可操作性:查看 32 位和 64 位的私有内存计数器。内存使用率将在 2 倍以内。现在使用应用程序更改节省一些内存。
标签: c# memory memory-management memory-leaks clr