Fastest way to copy a NativeList to a DynamicBuffer

Let’s say I have a MyBufferElement, NativeList and a DynamicBuffer

What’s the fastest way to copy the contents of the NativeList into the DynamicBuffer from within a job? Is there a better way than a for loop?


Context:
I have a satic utility function that is basically a “FillBufferWithThings(ref DynamicBuffer myBuffer)”, but I would like this utility function to also be usable with a NativeList. I thought the INativeList interface would allow me to use it for both NativeLists and DynamicBuffers, but it doesn’t have an Add() function. So I’m guessing the next best thing would be to make it work with a NativeList, but then we can copy the contents of the NativeList to a DynamicBuffer if we want to. But unless the copy is extremely fast, I’d rather just make two different functions. I might need to be copying 1000 lists of up to 10 elements per frame

UnsafeUtility.MemCpy? The nice thing about that is it is fast both in and out of Burst as it will always call into a native routine.

You can either use UnsafeUtility or you can use DynamicBuffer.AddRange(NativeArray) since NativeList can be implicitly converted to a NativeArray. I suspect that the UnsafeUtility is truly the faster way (I have not tested performance), but I prefer to avoid unsafe code whenever convient.

1 Like

AddRange just does a memcpy under the hood

public void AddRange(NativeArray<T> newElems)
{
    CheckWriteAccess();
    int elemSize = UnsafeUtility.SizeOf<T>();
    int oldLength = Length;
    ResizeUninitialized(oldLength + newElems.Length);

    byte* basePtr = BufferHeader.GetElementPointer(m_Buffer);
    UnsafeUtility.MemCpy(basePtr + (long)oldLength * elemSize, newElems.GetUnsafeReadOnlyPtr<T>(), (long)elemSize * newElems.Length);
}

Apart from some minor safety checks, it really isn’t going to be any different, just does all the work for you.

7 Likes