Skip to content
btsimonh edited this page Nov 11, 2017 · 3 revisions

This is a brief note about memory management when using long running, busy, large data apps in node.js.

UPDATE: Sudden realisation: nodejs does not know how big the matrix objects are, and so will NOT trigger GC before memory exhaustion!

History:

Whilst working on movement sensing using node-opencv in Node-Red, we found that after an upgrade to nodejs 8.9.0, the RPi3 we were on would regularly kill the node process, or dies itself, due to memory exhaustion. This was not so much of an issue in node 6.11.2

The processing we were doing was processing a continuous flow of video frames at anything from 7 fps to 30fps.

The below is what we (btsimonh and bartbutenaers) understand so far, and is not Official opinion of node-opencv; just noted here for posterity.

Some of this was tracked down to memory leakage in various new async aspects of node-opencv. However, having resolved everything we could find, it still occurred. It seems like sometimes nodejs just didn't get the free time to garbage collect... or maybe the --max_old_space_size=256 did not do what it says on the tin any more...

Anyway, the fact is that later version of node don't seem to like us.

We've not got to the bottom of exactly the best approach to the issue, but by combining the below approaches, we've achieved relatively stable memory usage:

  1. explicitly delete matrices as soon as you have finished with them.
  2. trigger a manual garbage collection every 10s.

UPDATE:

The better solution:

When you are done with your image matrix, call mtx.release(). This will release the memory that nodejs does not know about, only leaving the Matrix structure itself, which node will GC. Obviously do this carefully - you don't want to kill the data currently being processed by an async C++ thread, or referenced elsewhere in your JS. But then nodejs will stay within the memory limits you have told it about, and you don't have 200ms holes in your video flow.

Manual garbage collection

Bart found a way to access the garbage collection api without special node startup parameters (see his Node-Red node here), and it's worth highlighting here. Basically there is an API where you can change the startup parameters of the V8 engine after node has started (plagiarised directly from Bart's code; I don't know why he's runInNewContext() :) ):

require("v8").setFlagsFromString('--expose_gc');

gc = require("vm").runInNewContext('gc');

then, every time you want to do a manual gc,

gc();

Note that running a garbage collection is expensive; expect it to disrupt your video flow. But it's better to have a small pause every few seconds than a crash every 20 minutes....

Clone this wiki locally