Roslyn ObjectPool 结构体包装器

8
2个回答

5

这是一种常见的技巧,可避免设置引用类型的数组项时出现性能问题。在CLR(和JVM)上,数组是变体的。您可以将string写入object[]中。这需要运行时检查,以确保您没有实际上将string存储到SomethingElse[]中。使用该值类型技巧,无需在运行时执行该检查。


是的,有些代码设置了字段Value。但是没有任何代码会覆盖数组中的元素。鉴于Value是一个字段,在运行时没有类型检查,这使得你的答案无效。不是吗? - Sriram Sakthivel
1
不,这就是重点。重点是由于结构体是元素类型,需要移除运行时检查。如果没有它,将会有一个运行时检查。 - usr
好的。我可以直观地理解这里不需要运行时检查。但是有没有文章或其他东西谈论这个问题,我可以阅读更多? - Sriram Sakthivel
1
从生成的汇编代码中,我看到数组版本会发出一个 JIT_Ldelema_Ref,其中包含类型检查,而结构体版本可以直接加载地址。有关更多详细信息,请参见 https://github.com/dotnet/coreclr/blob/master/src/vm/jithelpers.cpp。 - Alois Kraus
问题不同,答案完全相同。我认为这不符合重复关闭的标准。 - usr
显示剩余3条评论

1
我认为这是出于性能方面的考虑。与类数组相比,结构体数组更受垃圾收集器的青睐。
来自避免自动GC收集的5个技巧和技术

对于一个类实例数组,GC必须检查该数组中的每个项,以查看它是否为活动对象(通用集合也是如此,它们使用内部数组)。 对于结构体数组,GC只需查看数组本身是否仍然是活动对象,因为结构体不能为null(即使对于可空结构体也是如此,它们只是使用内部跟踪机制来确定nullity)。 因此,在运行集合时,GC无需检查数千甚至数百万个项目!


如果是这样的话,CLR 就会始终包装所有数组元素而不需要进行 GC... 即使是结构体数组,如果其中包含引用,也必须遍历。 - usr
@usr 我明白你的想法。当我第一次阅读这篇文章时,我也持怀疑态度。也许作者的意思是仅适用于不包含任何引用的结构体数组。我们需要联系作者以了解更多细节。 - Sriram Sakthivel
垃圾回收器只能跳过值类型的数组,如果该类型本身不包含引用。否则它仍然必须遍历整个数组。 - Alois Kraus

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接