我有一个'服务'(owin / webapi + odp.net managed),它在x64机器上运行'server gc mode'。执行测试套件后,内存使用量约为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没有回收内存?
答案 0 :(得分:2)
好的窗户不能“强制”.Net来释放内存。虽然我不是.Net运行时的专家,但我的经验是,一旦你的应用程序开始消耗很多内容,.net框架就会保留在内存中。它会慢慢回复,因为它看起来很合适。从Windows的角度来看,它并不真正知道.Net会用它做什么,但它.Net已声称来自操作系统的内存,直到它(.net)将窗口返回窗口,无法将内存提供给另一个应用程序。 System.Byte []有几个400 + mb的块被保留,这可能表示存在内存泄漏。从操作系统的角度来看,框架已经请求了内存甚至使用了那个内存,所以直到它明确地(从框架而不是你)给出后面的窗口无法做任何事情。我会非常仔细地描述您的应用程序,因为.Net通常不释放内存的原因是因为您有内存泄漏。使用Visual Studio中的内存分析工具应该向您显示您是将内存“固定”还是只是保留它。真正坏的罪魁祸首通常是静态类变量/事件。
SO link:.NET Free memory usage (how to prevent overallocation / release memory to the OS)
答案 1 :(得分:0)
因为,Windows无法压缩应用程序以释放对象。您需要找到一种方法来定义应用程序的最大内存使用量。达到最大限制时,通过GC.Collect()手动调用垃圾收集器。
当应用程序运行时,尝试获取Process&设置maxLimit,类似于this