对于为什么在大型非托管分配之前调用 GC.Collect (在我的情况下,在创建大型(~250Mb)DirectX 资源之前)可以防止内存不足异常,我无法找到令人满意的解释。为什么托管堆的压缩允许非托管分配?
.Net 进程如何在托管堆和非托管堆之间共享其地址空间?
我最好的猜测是 .Net 进程在两种类型的堆和 GC 之间保持可移动的边界。Collect 允许该边界移动以支持更大的非托管堆。像这样的东西:
- (M)托管分配
- (U)n 托管分配
- (F) 自由记忆
- 进程地址空间 0-9
场景 #1 – 没有 GC.Collect
即将进行 3 个块的非托管分配,托管堆碎片化:
0123456789
MMFFMFFMFU
托管堆的“高水位标记”为 7
分配 3 个非托管块 -失败! 请注意,托管堆的高水位标记没有为非托管分配留下空间。
场景 #2 – 使用 GC.Collect
即将进行 3 个块的非托管分配,托管堆碎片化
0123456789
MMFFMFFMFU
托管堆的“高水位标记”为 7
调用 GC.Collect
0123456789
MMMMFFFFFU
托管堆的“高水位标记”为 3
分配 3 个非托管块 –成功!
0123456789
MMMMFFUUUU
这是它的工作原理吗?