【发布时间】:2013-07-20 06:18:28
【问题描述】:
我猜这个问题的答案是“不可能,切换到 C++”。但我想我还是会把它扔出去。
我正在处理一个巨大的二叉树。我有一个结构数组来表示我在遍历树时用来帮助处理内存局部性的分支节点。
为了节省一点内存,从而提高缓存局部性,我正在考虑重叠叶节点的对象引用。该对象引用将指向所有叶子数据。基本上是这样的:
[StructLayout(LayoutKind.Explicit)]
struct BranchData
{
[FieldOffset(0)] // 1 byte
internal byte SplitIndex;
[FieldOffset(1)] // 4 bytes
internal float SplitValue;
[FieldOffset(5)] // 4 bytes
internal int LowIndex;
[FieldOffset(9)] // 4 bytes
internal int HighIndex;
[FieldOffset(0)] // 8 bytes (We're working with x64 here)
internal LeafData Node;
}
上面给出了以下运行时错误
无法从程序集中加载类型“BranchData” 'WindowsFormsApplication1,版本=1.0.0.0,文化=中性, PublicKeyToken=null' 因为它在偏移量 0 处包含一个对象字段 未正确对齐或被非对象字段重叠。
我可以使用一个单独的数组来存储叶子数据,并使用索引指向该数组,但是我有 2 次内存查找(对于那些肯定是遥远的内存区域)。一个用于叶子数组中的位置以获取引用,一个用于获取叶子数据。如果我能实现这种重叠,我就会摆脱其中一个查找。
我能够固定对象并使用不安全的代码来解决这个问题。速度是这里的关键因素。
【问题讨论】:
-
我可能有一个答案,但我首先有几个问题: 1. 你能使用不安全的代码吗? 2. 如果不能使用不安全的代码,能否将对象固定在内存中?
-
@DanMcCann 我可以做到其中任何一个。我对代码的肮脏程度没有限制:-)
-
我在这里延伸了这个问题,但你能把问题移到另一个地方吗?假设您使用Neo4j 作为您的树并获得所有已经编写好的查询。您可能出现的性能问题会在其他地方出现,但在那里可能更容易解决。 FWIW
-
答案是,“不,你不能那样做。”运行时不允许您覆盖引用类型和值类型。我隐约记得曾在某一时刻找到规范的相关部分,但不记得在哪里。
-
@WillCalderwood 你有没有设法完成这项工作?
标签: c# .net performance memory-management