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

标签 c# garbage-collection unmanaged

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

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

以下是我的选择:

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

最佳答案

这是一个无可救药的无法回答的问题。固定对象不会减慢 GC 的速度,它只是 GC 压缩堆时路上的一 block 石头。只需跳过堆的固定部分,就可以轻松解决该问题。

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

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

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

关于c# - 多少 GCHandle 固定内存/对象会使垃圾收集器变慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17044063/

相关文章:

c# - 在 await Task.WhenAll() 中隔离异常

c# - 从 C# 调用非托管 .dll 的性能

msbuild - MSBuild托管与非托管属性

visual-studio - 如何使Visual Studios构建系统了解托管dll的非托管依赖关系?

c# - 第一次访问缓存时出现 IsolatedStorage 异常

c# - 使用 InsertOneAsync (.NET Driver 2.0) 插入新文档

.net - 对象在执行期间被垃圾收集?

java - 这个演示中的 JVM 内存分配和释放解释?

Java循环引用,糟糕的风格?

c# - try block 内的通用输出值赋值