【发布时间】:2015-11-02 09:20:25
【问题描述】:
我有一个在 x64 机器上以“服务器 gc 模式”运行的“服务”(owin/webapi + odp.net 托管)。执行测试套件后,内存使用量约为 2Gb。我在那台机器上“产生”了内存压力(另一个程序消耗了所有可用内存等等)。我期待 Windows 会强制 .net 释放一些内存。然而它没有。这是windbg的输出:
0:018> !dumpheap -stat
Statistics:
MT Count TotalSize Class Name
00007ffd10445b90 1 24 System.Collections.Generic.GenericEqualityComparer`1[[System.UInt64, mscorlib]]
...
00007ffd0f904918 100864 11616976 System.Object[]
0000005b19face20 84 1810674044 Free
Total 720544 objects
Fragmented blocks larger than 0.5 MB:
Addr Size Followed by
0000005b1c3c8800 425.6MB 0000005b36d56c50 System.Func`2[[System.IAsyncResult, mscorlib],[System.Net.HttpListenerContext, System]]
0000005c1c3fcf00 28.2MB 0000005c1e02be58 System.Reflection.Emit.MethodBuilder
0000005c1e02e5b0 268.0MB 0000005c2ec313d8 System.Threading.OverlappedData
0000005c2ec31678 142.3MB 0000005c37a830a0 System.Func`2[[System.IAsyncResult, mscorlib],[System.Net.HttpListenerContext, System]]
0000005d1c541aa0 404.8MB 0000005d35a1a958 System.Func`2[[System.IAsyncResult, mscorlib],[System.Net.HttpListenerContext, System]]
0000005d35a1e5a8 3.8MB 0000005d35df0c40 System.Func`2[[System.IAsyncResult, mscorlib],[System.Net.HttpListenerContext, System]]
0000005e1cfe7128 444.1MB 0000005e38c0c3f0 System.Byte[]
0000005e38c8cfb8 4.5MB 0000005e39110988 System.Byte[]
0000005e39111bf8 1.2MB 0000005e3923a570 System.Byte[]
0000005e3923b7e0 0.7MB 0000005e392ed7d0 System.Byte[]
0000005e392eea40 1.1MB 0000005e39401910 System.Byte[]
0:018> !heapstat
Heap Gen0 Gen1 Gen2 LOH
Heap0 455256040 24 24 3713672
Heap1 464550872 24 4327776 727456
Heap2 428541352 10344768 12616 24
Heap3 474250128 24 21350456 24
Total 1822598392 10344840 25690872 4441176
Free space: Percentage
Heap0 446429064 0 0 1819552SOH: 98% LOH: 48%
Heap1 459823968 0 144 152SOH: 98% LOH: 0%
Heap2 428520936 34904 24 24SOH: 97% LOH:100%
Heap3 474044952 0 336 24SOH: 95% LOH:100%
Total 1808818920 34904 504 1819752
所以只有大约 48Mb 实际使用和 1.8Gb 空闲,大部分内存不在 LOH 中,而是在 Gen 0 堆中,但 .net 不会归还该内存。同时系统正在缺乏内存。例如 IIS 无法启动,因为没有足够的内存。
为什么内存没有被windows回收?
【问题讨论】:
-
只有 4GB 内存的服务器?
-
16,但还有其他服务。我写道,我通过运行另一个占用所有可用内存的工具来模拟高内存压力
-
请先阅读问题。它不是 IIS,不是 SQL。如果您想知道,Oracle 正在另一个城市的数据中心的 linux 服务器上运行。我有运行多项服务的专用服务器,其中一项会消耗所有内存并且不会放弃。我可以在更大的数据集上运行我的测试并占据整个 16Gb。问题是只使用了 50Mb,而 .net 捕获 2Gb 并没有将其返回给操作系统。
-
几乎 1 GB 的
Func<IAsyncResult, HttpListenerContext>委托对象是不正常的。很难想象可以做到这一点的代码。伴随异步 I/O 的典型对象锁定很可能会炸毁 GC。 -
服务正在从 oracle 读取大结果。 10 列和 800K 行。因此,在读取数据库的响应时实际上使用了很多内存(存储结果的实现效率极低)。发送响应后,触发 gc 并回收内存。由于服务根据official documentation 在“服务器”模式下工作,因此“临时段”的大小为 2Gb,服务器服务正在运行。所以我想.net 不会将该段的一部分提供给操作系统。这听起来像真的吗?