I have an app that receives binary messages over a WebSocket frequently (at least once per frame) and plots the data, using canvas/webgl. I've noticed that I have a pretty good saw-tooth memory profile; lots of short lived chunks of data.
This does not surprise me since I'm receiving an object from onmessage
, at least once every 16ms, which is used for drawing and then de-referenced.
My question is: are there any tips for avoiding/minimizing this? Based on the WebSocket API, there doesn't seem to be an alternative to having new memory allocated on every socket receive call. In another language/environment, I'd pre-allocate some memory and receive into that buffer, to avoid constantly allocating memory for short lived objects, but I can't think of any obvious way to achieve this in JavaScript in the browser.
For reference, here is my Frames view.
I don't know if that idle time is garbage collection? Any dev-tools ninja insights would be greatly appreciated.
Not sure if I understood your problem but you can declare a global array like in any other language and use it as a circular buffer, for example:
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
}
}
Edit: I modified the answer to be more clear about the memory cycle:
JS will allocate memory for the received message on websockets and will create a reference to it called msg
that will be given to you as a param in the callback defined for onmessage
.
Note JS GC will only destroy that memory piece when it is not referenced anymore in the code.
What I do above is saving that reference inside a buffer so the value does not get destroyed when the callback is done and you can access it later using getNext
. You don't need to allocate new memory because JS did it for you.
In case you want to clone or create a different copy of msg
, there are some different options. A simple option that will allow you to clone a non-circular JSON object would be:
var newJSON = JSON.parse(JSON.stringify(msg));
You can find more information about memory allocation in JS in https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With