sho*_*der 5 .net c# garbage-collection heap-fragmentation memory-fragmentation
我正在运行一个服务HTTP请求的C#应用程序。我最近注意到,它占用的内存比我预期的要多。我抓起一些转储,将它们弹出到Windbg中,发现大部分内存都标记为“空闲”:
!dumpheap -stat
...
00007ffde4783630 681599 65433504 System.Threading.Tasks.TaskFactory+CompleteOnInvokePromise
00007ffde47cc988 167885 76872908 System.Byte[]
00007ffde47c6948 521353 80352802 System.String
0000007e3a16c2d0 1870425 1415374334 Free
Run Code Online (Sandbox Code Playgroud)
因此,转储约为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
Run Code Online (Sandbox Code Playgroud)
因此,我的小对象堆非常分散,特别是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
Run Code Online (Sandbox Code Playgroud)
下一步是使用!gchandles并寻找固定的手柄。这可能会识别锁定到特定内存位置的对象,因为某些本机代码(例如 C++)需要访问它。虽然垃圾收集可能会在内存中移动对象,但 .NET 不会更新 C++ 指针,因此固定是唯一的选择。
即使服务器上只有 1-2% 的可用 RAM,gen2 堆也不会被压缩。
您在这里谈论的是物理 RAM。对于操作系统,我期望它尽可能好地使用可用资源,因此我期望RAM 始终 100% 使用。如果它“未使用”,我希望操作系统将其用于缓存。因此,物理 RAM 使用情况不能真正作为垃圾回收的指标。
另外,我也不会太担心。如果 .NET 不使用内存,操作系统会将其交换到磁盘,从而释放物理 RAM 用于其他目的。
| 归档时间: |
|
| 查看次数: |
763 次 |
| 最近记录: |