WebSocket频繁onmessage零拷贝

set*_*hro 11 javascript browser garbage-collection memory-management websocket

我有一个应用程序经常通过WebSocket接收二进制消息(每帧至少一次)并使用canvas/webgl绘制数据.我注意到我有一个非常好的锯齿记忆配置文件; 很多短暂的数据块. 在此输入图像描述

这并不让我感到惊讶,因为我收到了一个对象onmessage,至少每16ms一次,用于绘图然后取消引用.

我的问题是:有没有避免/减少这个的提示?基于WebSocket API,似乎没有替代在每个套接字接收调用上分配新内存.在另一种语言/环境中,我会预先分配一些内存并接收到该缓冲区,以避免不断为短期对象分配内存,但我想不出任何明显的方法可以在浏览器的JavaScript中实现这一点.

作为参考,这是我的框架视图.

在此输入图像描述

我不知道那个空闲时间是垃圾收集吗?任何开发工具忍者见解将不胜感激.

Jav*_*nde 1

不确定我是否理解你的问题,但你可以像任何其他语言一样声明一个全局数组并将其用作循环缓冲区,例如:

var buffer = [];
var bufferLength = 1000;
var start = 0;
var end = 0;
var content = 0;

socket.onmessage(function(msg) { //msg allocated
    end %= bufferLength;
    if (end == start && content != 0)
        console.log("Buffer is full");
    else {
        content++;
        buffer[end++] = msg; //reference to msg saved so it's not destroyed at the end of the callback
    }
});

function getNext() {
    start %= bufferLength;
    if (start == end && content == 0)
        console.log("Buffer is empty");
    else {
        content--;
        return buffer[start++]; // returns reference to next msg
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:我修改了答案以更清楚地了解内存周期:

JS 将为 websockets 上接收到的消息分配内存,并创建一个名为该消息的引用,msg该引用将作为为 定义的回调中的参数提供给您onmessage

注意,JS GC 仅当代码中不再引用该内存块时才会销毁该内存块。

我上面所做的是将引用保存在缓冲区内,以便回调完成时该值不会被破坏,并且您可以稍后使用getNext. 你不需要分配新的内存,因为 JS 已经帮你做了。

如果您想克隆或创建 的不同副本msg,有一些不同的选项。允许您克隆非循环 JSON 对象的一个​​简单选项是:

var newJSON = JSON.parse(JSON.stringify(msg));
Run Code Online (Sandbox Code Playgroud)

您可以在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management中找到有关 JS 内存分配的更多信息