我正在运行一个为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%的内存可用,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发布于 2017-11-25 15:50:31
下一步是使用!gchandles并查找固定句柄。这可能会识别锁定到特定内存位置的对象,因为某些本机代码(例如C++)需要访问它。虽然垃圾处理可能会在内存中移动对象,但是C++指针不会被.NET更新,因此钉扎是唯一的选择。
即使服务器上只有1-2%的内存可用,gen2堆也没有压缩。
你说的是物理内存。从一个操作系统中,我认为它尽可能好地使用了可用的资源,所以我希望RAM在任何时候都能被100%地使用。如果“不使用”,我希望操作系统使用它进行缓存。因此,物理RAM的使用不能真正成为垃圾收集的指示符。
而且,我也不会太担心。如果.NET不使用内存,它将被操作系统交换到磁盘上,从而释放物理内存用于其他用途。
https://stackoverflow.com/questions/47480337
复制相似问题