多少 GCHandle 固定内存/对象会使垃圾收集器变慢?

Ped*_*o77 5 c# garbage-collection unmanaged

我确信这个答案将取决于用户机器,但必须有一些关于固定数据的最佳实践

我需要保存 5 个字节数组,每个数组包含 1.048.576 个字节。通常我更喜欢使用GCHandle(托管)内存,但有些人说它会减慢 GC。我知道这可能发生,但是需要固定多少内存/对象才能开始真正影响 GC?

以下是我拥有的选项:

  1. GCHandle.Alloc GCHandleType.Pinned(管理)。它会减慢GC??
  2. Marshal.AllocHGlobal(非托管访问)。不安全代码
  3. 使用 aBitmap在 Scan0 中保存数据(非托管访问)。不安全代码

Han*_*ant 6

这是一个无可救药的无法回答的问题。固定对象并没有那么慢地减慢 GC,当 GC 压缩堆时,它只是路上的一块石头。只需跳过堆的固定部分,就可以轻松地绕过那块石头。

更糟糕的结果是它会对收集完成运行的代码产生持久影响。由于堆没有被压缩得那么好,引用的局部性不是那么好,因此处理器将无法从 CPU 缓存中获得尽可能多的里程。量化这种减速是不可能的,这在很大程度上取决于之后运行的代码类型。只是它更糟并持续了一段时间,直到下一次 GC。

唯一的好建议是,如果您必须固定,请尽可能缩短固定时间。并避免可能发生的集合的场景,而物体被固定。粗略地说,这意味着您避免在持有 pin 时分配内存。如果程序运行多个线程,则并不总是实用,从而使<gcServer>.config 文件中的元素具有吸引力。它选择了一种不同的 GC 策略,该策略使用更多内存但为线程提供自己的 GC 堆段。没有简单的指南来确定何时执行此操作,需要使用实际数据集进行分析。

Marshal.AllocHGlobal 和 Bitmap 都对 GC 堆没有任何显着影响,它们是从非托管内存堆分配的。