Часто задаваемые вопросы по WebSocket

У меня есть приложение, которое часто получает двоичные сообщения по WebSocket (по крайней мере один раз за кадр) и обрабатывает данные, используя canvas/webgl. Я заметил, что у меня неплохой профиль памяти пилы; много недолговечных кусков данных. введите описание изображения здесь

Это меня не удивляет, так как я получаю объект от onmessage, по крайней мере один раз каждые 16 мс, который используется для рисования и затем отменяется.

Мой вопрос: есть ли советы по предотвращению/минимизации этого? Основанный на API WebSocket, похоже, нет альтернативы наличию новой памяти для каждого вызова приема сокета. На другом языке/среде я предварительно выделил некоторую память и получал в этот буфер, чтобы избежать постоянного выделения памяти для короткоживущих объектов, но я не могу придумать какой-либо очевидный способ добиться этого в JavaScript в браузере.

Для справки, вот мое представление Frames.

введите описание изображения здесь

Я не знаю, является ли это время простоя сборкой мусора? Любые идеи разработчика ниндзя будут очень полезны.

Ответ 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 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
    }
}

Изменить: я изменил ответ, чтобы узнать больше о цикле памяти:

JS будет выделять память для принятого сообщения на веб-сайтах и ​​создаст ссылку на него под названием msg, которая будет предоставлена ​​вам в качестве параметра в обратном вызове, определенном для onmessage.

Примечание. JS GC уничтожит только эту часть памяти, если в коде больше не упоминается.

То, что я делаю выше, сохраняет эту ссылку внутри буфера, поэтому значение не уничтожается, когда обратный вызов завершен, и вы можете получить к нему доступ позже, используя getNext. Вам не нужно выделять новую память, потому что JS сделал это для вас.

Если вы хотите клонировать или создавать другую копию msg, есть несколько разных параметров. Простым вариантом, который позволит вам клонировать некруглый объект JSON, будет:

var newJSON = JSON.parse(JSON.stringify(msg));

Дополнительную информацию о распределении памяти в JS можно найти в https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management