C#中的内存布局优化

Memory layout optimization in C#

免责声明:下面的措辞可能存在一些误解,如果我误解了我的代码是在 C# 中处理的,从我编写它到它看起来像零和一的那一刻,请纠正我

问题如下(已链接):

在 C# 中,无论我是否使用优化技术,我的数据结构 and/or 我的数据操作实现是否有任何方法会对性能产生影响?

编译器在输出IL时是做什么的,靠谱吗? 意思是:如果我让我的数据成为 SOA,它会是 IL 中的 SOA 吗?总是?

当 JIT 读取 IL 时,我的数据结构会发生什么变化?它改变了吗?它是否自动优化以适应我的处理器?

对比:that talk about C/C++

我知道这个演讲是针对本机代码的,讨论处理器布局与本机代码中的数据布局的具体细节。

我也知道 C# 编译器和 JIT 编译器会针对这些问题为我优化内容。

基本上我想知道这些优化是否会对我的性能产生影响:

我从事游戏开发工作,性能至关重要,我们处理大量数据,我们需要每秒至少处理 24 次,我不能让 GC 处理 300 毫秒或内存 accessed/allocated 当我试图检测 3000 个不同对象之间的碰撞时到处都是

关于我阅读但没有真正回答问题的内容的参考:

但是这些并没有回答与处理器和数据布局实施相关的性能成本。


在 Hans 回答之后更进一步:

当你说:"You can pursue SOA but that doesn't help. Yes, your program will slow down because of all that structure copying and does so in a deterministic way. But it doesn't stop the rain. You get the worst of both, a slow program and the exact same pauses."

这并不意味着我的程序没有从 SOA 中受益,它会(可能)更快,因为它有助于处理我的数据。只是对GC本身没有影响。

另一件事是,如果我不对我的数据布局进行 SOA 或其他改进,编译器就不会为我改进它,对吗?我不能依靠编译器来处理那种事情吗?

担心GC就像担心今天会不会下雨。迟早要下雨,你无能为力。 需要,否则就无法让草坪看起来很绿。你永远不想做的是故意阻止下雨。因为如果你这样做,它会倾盆大雨,淹没那片漂亮的草坪。持续的毛毛雨是你想要的。最好在晚上不看的时候。

.NET GC 强烈支持这一点。只有小型 gen #0 和 #1 集合会暂停您的程序。当您的代码继续执行时,昂贵的 gen#2 收集在后台发生。最坏情况下的暂停徘徊在接近一百微秒的某个地方。这与 其他 程序在现代 OS 上暂停的原因几乎没有区别。就像您的游戏循环暂时暂停一样,因为另一个更高优先级的内核线程需要 运行。只是一场毛毛雨,肉眼看不到。

您可以追求 SOA,但这无济于事。是的,你的程序会因为所有的结构复制而变慢,并且是以一种确定的方式进行的。但这并不能阻止雨。你得到了两者中最糟糕的,一个缓慢的程序 完全相同的暂停。

不用担心下雨,只要确保它在正确的时间下。要利用后台 GC,您需要构建数据,使其存在时间非常短,因此它很容易随着 gen #0/1 收集而消失。或者活了很长时间,所以它在第 2 代找到了一个舒适的家,并在那里呆了一段时间。这通常是程序中非常常见的模式,尤其是在游戏中。你不太可能需要做任何事情。