Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IArrayBuffer.WriteBytes taking a span/memory? #632

Open
oconnor0 opened this issue Jan 28, 2025 · 2 comments
Open

IArrayBuffer.WriteBytes taking a span/memory? #632

oconnor0 opened this issue Jan 28, 2025 · 2 comments
Assignees

Comments

@oconnor0
Copy link

oconnor0 commented Jan 28, 2025

I have a situation where I have some data sitting in a class that exposes access to a ReadOnlyMemory<bytes>. I'd like to be able to move the bytes directly from this into V8 via IArrayBuffer.WriteBytes, but I have to convert the ReadOnlyMemory to a byte[] and then copy that in. Would it be feasible to add a method like the following to IArrayBuffer?

ulong WriteBytes(
	ReadOnlySpan<byte> source,
	ulong offset
)

I believe the conversion from ReadOnlyMemory to ReadOnlySpan is fast and should avoid one copy of the byte array.

I guess this is somewhat dependent on WriteBytes immediately writing the bytes from C# to V8 vs keeping a reference to the source around.

This is not a high priority for me, just something I noticed today.

@ClearScriptLib
Copy link
Collaborator

Hi @oconnor0,

Yes, fast data transfer from spans to array buffers and vice versa makes perfect sense.

Thanks for suggesting it!

@ClearScriptLib
Copy link
Collaborator

ClearScriptLib commented Jan 29, 2025

Hi @oconnor0,

By the way, it's already possible to do the copy without creating a byte array.

First, let's set up a ReadOnlyMemory<byte> and an ArrayBuffer:

const int size = 16;
var array = Enumerable.Range(0, size).Select(Convert.ToByte).ToArray();
var memory = new ReadOnlyMemory<byte>(array);
using var buffer = (IArrayBuffer)engine.Evaluate($"new ArrayBuffer({size})");

In this example, the ReadOnlyMemory<byte> is backed by a managed array, but it could just as well refer to unmanaged memory. Here's how to copy data from the ReadOnlyMemory<byte> to the ArrayBuffer without creating an intermediate array:

buffer.InvokeWithDirectAccess(pBuffer => {
    unsafe {
        using var hMemory = memory.Pin();
        Buffer.MemoryCopy(hMemory.Pointer, pBuffer.ToPointer(), size, size);
    }
});

The only allocation here is of the delegate passed to InvokeWithDirectAccess, but ClearScript 7.5 will provide a way to avoid that too.

Good luck!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants