在不复制的情况下通过 WebSocket 发送 ArrayBuffer 的子段 [英] Sending a sub-segment of an ArrayBuffer over a WebSocket without copying

查看:44
本文介绍了在不复制的情况下通过 WebSocket 发送 ArrayBuffer 的子段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用要通过 WebSocket 发送的数据填充 ArrayBuffer.

I am populating an ArrayBuffer with data to be sent over a WebSocket.

数据大小可变,因此在序列化时我会根据需要动态扩展 ArrayBuffer.

The data has variable size, so while serialising I dynamically extend the ArrayBuffer as needed.

但是,当序列化过程完成时,我不想发送缓冲区末尾的未使用空间.

However when the serialisation process completes I often have unused space at the end of the buffer that I do not want to send.

可以将所需部分复制到新的 ArrayBuffer 中,但这会浪费内存和 CPU.

It's possible to copy the required section out to a new ArrayBuffer, but this is wasteful in terms of memory and CPU.

是否可以在不复制的情况下通过 WebSocket 发送 ArrayBuffer 的子部分?如果没有,我还有其他方法可以避免复制对性能的影响吗?

Is it possible to sent a sub-portion of an ArrayBuffer over a WebSocket without copying? If not, is there another way I can go about this that will avoid the performance hit of copying?

进行一些澄清编辑.

核心问题在于WebSocket.send 只接受 DOMStringArrayBufferBlob.这些似乎都需要一个完整的缓冲区,而不是缓冲区的视图.

The core problem is that WebSocket.send only accepts DOMString, ArrayBuffer or Blob. These all seem to require a complete buffer, not a view onto a buffer.

我不知道开始序列化时缓冲区有多大,所以它从 64 字节开始,每次溢出时都会加倍.这已经一些复制,但我可以调整初始大小,以便溢出是例外.我想避免的是必须将序列化数据从过大的缓冲区中复制出来.

I do not know how big the buffer will be when I start serialisation, so it starts at 64 bytes and doubles on each overflow. That's already some copying, but I can tune the initial size so that overflows are the exception. What I want to avoid is having to copy the serialised data out of the over-sized buffer.

在伪 JS 中:

function serialiseAndSend(webSocket, message) {

    // Allocate a buffer (assume it's large enough)
    const buffer = new ArrayBuffer(64);

    // Serialise into that buffer, and obtain the number of bytes written (<= 64)
    const bytesWritten = serialise(buffer, message);

    // The first 'bytesWritten' bytes of 'buffer' contain my message, the rest is zeroed.
    //
    // I want to send that sub-portion without allocating another buffer.

    // This function would be great (buffer, start, count) but doesn't exist
    webSocket.send(buffer, 0, bytesWritten); 

    // Instead I think I have to allocate and send a copy
    const copy = buffer.slice(0, bytesWritten);
    webSocket.send(copy);
}

这种模式在其他平台/语言上很常见,似乎是 WebSocket API 中的一个疏忽.但是我知道它是由经验丰富的开发人员设计的,我希望有一种方法可以做到我还没有遇到过的事情.

This pattern is common on other platforms/languages, and seems like an oversight in the WebSocket API. However I know it was designed experienced developers and am hoping there's a means to do what I'm after that I haven't encountered yet.

推荐答案

编辑、更新

MDN 不是 规范.关于 WebSocket.send() 方法的 MDN 文档省略了 ArrayBufferView 选项包含在实际规范中,参见 https://bugzilla.mozilla.org/show_bug.cgi?id=1409752.

MDN is not the specification. The MDN documentation as to .send() method of WebSocket omits the ArrayBufferView option included at the actual specification, see https://bugzilla.mozilla.org/show_bug.cgi?id=1409752.

您可以使用.subarray() 创建一个现有 TypedArray

还要注意,这是在现有缓冲区上创建一个新视图;对新对象内容的更改将影响原始对象反之亦然.

Also note that this is creating a new view on the existing buffer; changes to the new object's contents will impact the original object and vice versa.

这篇关于在不复制的情况下通过 WebSocket 发送 ArrayBuffer 的子段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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