【发布时间】:2017-10-12 20:29:14
【问题描述】:
我正在用要通过WebSocket 发送的数据填充ArrayBuffer。
数据大小可变,因此在序列化时我会根据需要动态扩展ArrayBuffer。
但是,当序列化过程完成时,我通常在缓冲区末尾有我不想发送的未使用空间。
可以将所需的部分复制到新的ArrayBuffer,但这在内存和 CPU 方面是浪费的。
是否可以在不复制的情况下通过WebSocket 发送ArrayBuffer 的子部分?如果没有,是否有其他方法可以避免复制对性能的影响?
进行一些澄清编辑。
核心问题是WebSocket.send只接受DOMString、ArrayBuffer或Blob。这些似乎都需要一个完整的缓冲区,而不是缓冲区的视图。
我不知道当我开始序列化时缓冲区会有多大,所以它从 64 字节开始,每次溢出时翻倍。这已经是 一些 复制,但我可以调整初始大小,以便溢出是例外。我要避免的是必须将序列化数据从过大的缓冲区中复制出来。
在伪 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 的疏忽。但是我知道它是由经验丰富的开发人员设计的,我希望有一种方法可以完成我尚未遇到的事情。
【问题讨论】:
-
"核心问题是
WebSocket.send只接受DOMString、ArrayBuffer或Blob"这不准确。.send()也接受TypedArray作为参数。 “这个函数很好(缓冲、启动、计数)但不存在” 使用.subarray()时确实存在该选项,如答案webSocket.binaryType = "arraybuffer"; let ab = new Uint8Array(buffer); let segment = ab.subarray(0, bytesWritten); webSocket.send(segment)所示。注意,.slice()与.subarray()不同 -
"核心问题是
WebSocket.send只接受DOMString、ArrayBuffer或Blob"注意,MDN不是规范,实际的@987654322 @ 还包括ArrayBufferView作为.send()的预期参数,它们是TypedArrays。 MDN 文档可能应该被编辑和更新以包含该遗漏。
标签: javascript websocket