结构内存破解重叠对象的引用 - 这可能吗? [英] Struct memory hack to overlap object reference - Is it possible?

查看:287
本文介绍了结构内存破解重叠对象的引用 - 这可能吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我猜这个问题的答案将是这是不可能的,切换到C ++。但我想我扔在那里呢。

I'm guessing the answer to this is going to be "It's not possible, switch to C++". But I thought I'd throw it out there anyway.

我处理一个巨大的二叉树。我有结构的数组重新present,我用它来帮助记忆局部性通过树遍历时,分支节点。

I'm dealing with a massive binary tree. I've got an array of structs to represent the branch nodes that I use to help with locality of memory when iterating through the tree.

要节省一点的内存,并因此提高缓存的局部性我期待在重叠的叶节点对象引用。这个对象引用指向所有叶子的数据。基本上是这样的:

To save a bit of memory, and therefore improve cache locality I'm looking at overlapping an object reference for leaf nodes. That object reference will point to all the leaf data. Basically, something like this:

[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;
}

上面提供了以下运行时错误

The above gives the following runtime error

未能从程序集加载类型BranchData   WindowsFormsApplication1,版本= 1.0.0.0,文化=中立,   公钥=空',因为它包含了一个对象字段的偏移量为0   不正确地对齐或重叠由非对象字段

Could not load type 'BranchData' from assembly 'WindowsFormsApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because it contains an object field at offset 0 that is incorrectly aligned or overlapped by a non-object field.

我可以用一个单独的阵列来存储数据叶,并使用索引指向数组,但我有2个内存查找(什么是内存肯定偏远地区)。一个用于叶阵列中的位置,以获得参考,和一个到达叶数据。如果我能做到这一点重叠,我摆脱那些查找之一。

I could use a separate array to store the leaf data, and use the indexes to point to that array, but then I have 2 memory lookups (for what are certainly distant areas of memory). One for the location in the leaf array to get the reference, and one to get the leaf data. If I can achieve this overlap, I get rid of one of those lookups.

我能够针对象,并使用不安全的code,以解决这个问题。速度是关键因素在这里。

I am able to pin objects and use unsafe code to solve this problem. Speed is the key element here.

推荐答案

这限制是管理code非常基本的。问题是,你的节点的成员是一个对象引用。指针在运行时。它是由其他字段重叠

This restriction is very fundamental in managed code. The problem is that your Node member is an object reference. A pointer at runtime. It is overlapped by the other fields.

垃圾收集器需要能够发现指针返回。既要知道,有一个活引用堆上的LeafData对象。并更新该指针时,当堆被压缩的LeafData对象移动。

The garbage collector needs to be able to find that pointer back. Necessary both to know that there's a live reference to the LeafData object on the heap. And to update that pointer when the LeafData object is moved when the heap is compacted.

问题是:有没有办法使收集器可以判断是否你的工会商店的指针。如果它不那么有一个风险,即其他成员的值将的像一个有效的对象引用到GC。这是非常,非常糟糕。

Problem is: there's no way that the collector can tell whether your union stores that pointer. If it doesn't then there's a risk that the values of the other members will look like a valid object reference to the GC. And that's very, very bad.

存储不安全LeafData *在技术上是可能的,但需要的LeafData对象进行固定。当树大,GC倒了没事的时候可以再移动就不能正常工作。在非托管的存储方式的LeafData数据进一步下跌的兔子洞,你开始届时来写C ++ code。你唯一可以做的另一件事是存储LeafData在节点本身,作为一个结构,pretty的可能性不大,你会很高兴与配合。

Storing an unsafe LeafData* is technically possible but that requires the LeafData object to be pinned. That just can't work when the tree is big, the GC falls over when nothing can be moved anymore. Storing the LeafData data in unmanaged memory is further down the rabbit hole, you are starting to write C++ code by then. The only other thing you could do is store the LeafData in the node itself, as a struct, pretty unlikely you'll be happy with the fit.

请注意,你应该避免这些不对齐的领域,你会得到抨击pretty的辛苦,当字段跨越的L1缓存线边界。把SplitIndex的的HighIndex所以这是不可能发生的。

Do note that you should avoid these misaligned fields, you'll get slammed pretty hard when a field spans an L1 cache line boundary. Put the SplitIndex after HighIndex so this can't happen.

这篇关于结构内存破解重叠对象的引用 - 这可能吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆