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.
I\'m dealing with a massive binary t
I don't know if this is faster in practice, but it has fewer memory lookups in managed code.
(There might be more lookups in the CLR itself that I'm not aware of.)
That said, you can use GCHandle
to overlay managed references with unmanaged data:
[StructLayout(LayoutKind.Explicit)]
public struct Data
{
[FieldOffset(0)]
public IntPtr NativeData;
[FieldOffset(0)]
public GCHandle Handle;
}
Data data = ...;
((YourClass)data.Handle.Target).Blah();
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.
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.
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.
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.
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.