我们有一个 asp.net (.net 4.0) web 应用程序,安装在多个环境中。在大多数环境中,内存使用量约为 1GB。但是,我们有一个环境,其中内存使用量峰值为 5.5GB。这是在一台具有 4 个内核和 8GB RAM 的 Server 2008 计算机上运行的 VMWare esx 客户端。
我设置了性能计数器,结果如下:
Memory
Committed Bytes 10 145 739 948,0000
Pages Output/sec 0,0000
Paging File _Total
% Usage 28,998
Process _Total w3wp
Working Set 7 480 003 280 5 604 421 056
我还对 w3wp 进程进行了内存转储(当时内存为 +/-2GB,因为更大的转储失败了)。在转储上运行 DebugDiag 并没有让我变得更明智。似乎 .net 本身只占用了 800MB,大部分内存被“其他东西”占用了。
.NET GC Heap Information
GC Heap Size 826,09 MBytes
Total Commit Size 1217 MB
Total Reserved Size 16190 MB
Heap Analysis
Summary
Number of heaps 29 Heaps
Total reserved memory 1,89 GBytes
Total committed memory 1,79 GBytes
...
(largest of the Heaps)
Reserved memory 1,69 GBytes
Committed memory 1,67 GBytes(99,14% of reserved)
Uncommitted memory 14,86 MBytes(0,86% of reserved)
Number of heap segments 113 segments
Number of uncommitted ranges 113 range(s)
Size of largest uncommitted range 0 Bytes
问题是我不确定这种高内存使用率是否是个问题。所以我正在寻找一些关于如何处理这个问题的指导:
- 或者有人告诉我这只是 IIS7 的工作方式,我不应该担心内存。
- 或者有人告诉我如何进一步分析这个转储(特别是如何查看 1.6GB 堆里有什么)。
- 或者向我解释一下为什么.net 使用的和 W3WP 使用的有这么大的差异。
如您所见,所有堆中的总字节数为 1.12GB。当时,W3WP 使用了 6.4GB。为什么这两个数字之间会有这么大的差异?什么东西会占用这个空间?这是我看到的 LOH 碎片吗?
答案1
这实际上更多的是开发人员的问题,与 IIS 无关。
您应该做的第一件事是确定内存位于哪一代堆(0、1、2 或 3(大型对象堆))
Process Explorer 提供了一种显示此信息的简单方法。
在大多数情况下,.NET GC 是自我管理的。有一些 .config 参数可以调整这一点,但这确实是开发人员应该提供指导的领域。
如果您想检查堆,WinDbg 可能是首选工具。
http://blogs.microsoft.co.il/sasha/2010/08/24/psscor2-object-inspection-commands-part-2/
http://blogs.microsoft.co.il/sasha/2010/08/26/psscor2-gc-heap-analysis-commands/
答案2
对于那些最终遇到类似问题的人来说:最终是 .net 框架的 Active Directory 库中的非托管代码未得到正确处理。这就是非托管堆如此之大的原因。
我如何找出罪魁祸首?我最终只能查看随机内存地址来找出内容。因为我找到了一个很多Active Directory 相关数据,我知道这正在泄露数据。
打了几次Dispose()
电话后,问题就解决了。