在不复制的情况下通过 WebSocket 发送 ArrayBuffer 的子段 [英] Sending a sub-segment of an ArrayBuffer over a WebSocket without copying
问题描述
我正在用要通过 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
只接受 DOMString
、ArrayBuffer
或 Blob
.这些似乎都需要一个完整的缓冲区,而不是缓冲区的视图.
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屋!