通过WebSocket发送ArrayBuffer的子段而不进行复制

时间:2017-10-12 20:29:15

标签: javascript websocket

我正在填充ArrayBuffer,其中包含要通过WebSocket发送的数据。

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

然而,当序列化过程完成时,我经常在缓冲区的末尾有一些我不想发送的空间。

可以将所需的部分复制到新的ArrayBuffer,但这在内存和CPU方面是浪费的。

是否可以在ArrayBuffer上发送WebSocket的子部分而无需复制?如果没有,是否还有另一种方法可以避免复制的性能损失?

进行一些澄清。

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

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

在psuedo-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的疏忽。但是我知道它是由经验丰富的开发人员设计的,我希望有一种方法可以做我之前没有遇到过的事情。

1 个答案:

答案 0 :(得分:2)

修改,更新

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

您可以使用.subarray()为现有TypedArray

创建新视图
  

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