我正在运行一款处理HTTP请求的C#应用程序。最近我发现它所占用的内存比我预期的还要多。我获取了一些转储文件,通过Windbg打开后发现大部分内存都被标记为“Free”:
!dumpheap -stat
...
00007ffde4783630 681599 65433504 System.Threading.Tasks.TaskFactory+CompleteOnInvokePromise
00007ffde47cc988 167885 76872908 System.Byte[]
00007ffde47c6948 521353 80352802 System.String
0000007e3a16c2d0 1870425 1415374334 Free
因此,这个转储文件大约有3GB大小,其中约有一半是空闲内存。查看堆栈时,我看到了这个:
!heapstat
Heap Gen0 Gen1 Gen2 LOH
Heap0 82248472 7354560 987275056 178834656
Heap1 93146552 6382864 857470096 129435960
Total 175395024 13737424 1844745152 308270616
Free space: Percentage
Heap0 40969256 146456 640426720 54829792 SOH: 63% LOH: 30%
Heap1 75943736 94448 550812312 54825216 SOH: 65% LOH: 42%
Total 116912992 240904 1191239032 109655008
我的小对象堆非常碎片化,特别是Gen2。在服务器上,我可以看到Gen2集合正在发生(使用性能计数器),但即使它们是,看起来Gen2堆也没有被压缩。即使服务器上只有1-2%的RAM可用,Gen2堆也不会被压缩。
对我而言,这似乎是因为堆被碎片化而导致的内存压力。然而,我无法弄清楚为什么会发生碎片化,或者为什么Gen2不能被压缩。一些空闲空间的大小为6MB,所以我认为它一定会将这些空间压缩掉。
有人可以给我一些想法,帮我找出为什么我的堆如此碎片化吗?我是否在错误的方向上努力?
任何帮助都将不胜感激,谢谢!
编辑1:
`!gchandles`的细分如下:
Handles:
Strong Handles: 4507
Pinned Handles: 58
Async Pinned Handles: 977
Ref Count Handles: 1
Weak Long Handles: 6087
Weak Short Handles: 724