NET 某光电成像后端解析系统 内存暴涨分析
为什么会暴涨由于是linux上的.net原来的 !address -summary 就彻底失去功效了使用高版本的sos自带的全平台替换版 !maddress 去搞定输出结果如下0:000 !maddress0:000 !maddress±-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| Memory Kind | StartAddr | EndAddr-1 | Size | Type | State | Protect | Image |±-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| Stack | ffc81c7a0000 | ffc81cfa0000 | 8.00mb | MEM_PRIVATE | MEM_COMMIT | PAGE_READWRITE | || Stack | ffc81cfb0000 | ffc81d7b0000 | 8.00mb | MEM_PRIVATE | MEM_COMMIT | PAGE_READWRITE | || Stack | ffc81e7e0000 | ffc81efe0000 | 8.00mb | MEM_PRIVATE | MEM_COMMIT | PAGE_READWRITE | || Stack | ffc81eff0000 | ffc81f7f0000 | 8.00mb | MEM_PRIVATE | MEM_COMMIT | PAGE_READWRITE | |±------------------------------------------------------------------------| Memory Type | Count | Size | Size (bytes) |±------------------------------------------------------------------------| Stack | 314 | 3.65gb | 3,918,856,192 || GCHeap | 384 | 3.02gb | 3,240,099,840 || PAGE_READWRITE | 1,151 | 175.37mb | 183,889,536 || Image | 622 | 115.80mb | 121,428,352 || LowFrequencyHeap | 33 | 6.31mb | 6,619,136 || HighFrequencyHeap | 10 | 6.19mb | 6,488,064 || LoaderCodeHeap | 7 | 5.00mb | 5,242,880 || PAGE_READONLY | 131 | 4.26mb | 4,466,176 || PAGE_EXECUTE_WRITECOPY | 7 | 704.00kb | 720,896 || ResolveHeap | 1 | 512.00kb | 524,288 || DispatchHeap | 1 | 384.00kb | 393,216 || StubHeap | 1 | 192.00kb | 196,608 || IndirectionCellHeap | 1 | 64.00kb | 65,536 || CacheEntryHeap | 1 | 64.00kb | 65,536 || LookupHeap | 1 | 64.00kb | 65,536 || HostCodeHeap | 1 | 64.00kb | 65,536 |±------------------------------------------------------------------------| [TOTAL] | 2,666 | 6.97gb | 7,489,187,328 |±------------------------------------------------------------------------看到卦中的这些信息秤砣终于落地了总计吃了6.97G的内存主要都是被 Stack 和 GCHeap 给吃掉了。为什么 Stack 吃了这么多熟悉 linux 的朋友应该知道默认情况下 Stack 会吃掉 8M 的内存这在上面的 items 上也能看出究竟不过有点讽刺的是在微软的官方MSDN上居然没找到 DOTNET_DefaultStackSize 变量的解释只在一些野路子中发现了端倪下面图中小哥的大胡子我咋看起来 quite sexual 截图如下imageimage搞清楚前因后果之后处理起来就比较简单了使用环境变量即可不过这东西也有自己的限制设置不了主线程DOTNET_DefaultStackSize180000如果将StackSize从 8M - 1.5M那 Stack 所侵占的内存就彻底搞定啦。为什么 GCHeap 吃了这么多要想找到这个问题的答案直接 !eeheap -gc 观察托管堆即可。0:000 !eeheap -gcDATAS Number of GC Heaps: 128…Heap 126 (0000aaacefcfe750)generation 0 starts at ffed4400c468generation 1 starts at ffed4400c450generation 2 starts at ffed44000000ephemeral segment allocation context: noneSmall object heapsegment begin allocated committed allocated size committed sizeffed43ff0000 ffed44000000 ffed4400c480 ffed44f80000 0xc480 (50304) 0xf80000 (16252928)Large object heap starts at fff5a4000000segment begin allocated committed allocated size committed sizefff5a3ff0000 fff5a4000000 fff5a44da1e8 fff5a4590000 0x4da1e8 (5087720) 0x590000 (5832704)Pinned object heap starts at fffda4000000segment begin allocated committed allocated size committed sizefffda3ff0000 fffda4000000 fffda4000018 fffda4010000 0x18 (24) 0x10000 (65536)Heap 127 (0000aaacefd2fc70)generation 0 starts at ffed84028fe8generation 1 starts at ffed84028d90generation 2 starts at ffed84000000ephemeral segment allocation context: noneSmall object heapsegment begin allocated committed allocated size committed sizeffed83ff0000 ffed84000000 ffed84029000 ffed84fa0000 0x29000 (167936) 0xfa0000 (16384000)Large object heap starts at fff5b4000000segment begin allocated committed allocated size committed sizefff5b3ff0000 fff5b4000000 fff5b4668240 fff5b4810000 0x668240 (6718016) 0x810000 (8454144)Pinned object heap starts at fffdb4000000segment begin allocated committed allocated size committed sizefffdb3ff0000 fffdb4000000 fffdb4004030 fffdb4010000 0x4030 (16432) 0x10000 (65536)GC Allocated Heap Size: Size: 0x3577ef58 (897052504) bytes.GC Committed Heap Size: Size: 0xc1200000 (3240099840) bytes.从卦中数据看有经验的朋友马上就条件反射出这是个啥问题对我经常说的内存黑洞即用handful的数据直接撬开了数十倍甚至数百倍的自身内存比如上面 897M 撬开了 3.24G。虽然程序中有快进快出的现象但这里也有一个不可忽视的客观条件即程序中居然有 128 个heap这就说明机器是 128core的哈哈这么多核心的cpu我估计内存也不小一查果然是 254G 内存某些行业真的是高富帅哈。。。输出如下0:000 dp libcoreclr!SVR::gc_heap::total_physical_mem L10000fffe4b0b71f8 0000003f88bc00000:000 ? 0000003f88bc0000 /0n1024/0n1024/0n1024 Evaluate expression: 254 00000000000000fe再次观察托管堆你会发现 allocated size 和 committed size 相距不像我之前分析的程序会有那么大这里也仅仅10多M左右结果坏就坏在核心数太多直接翻了128倍导致了最后的的悲剧发生。所以这个问题的解决思路也比较简单两个路子。升级到 .NET10使用自带的 DATAS 机制。