11

Overview

I've done some reading on JavaScript memory management in the past, and am aware of the issue with circular DOM references, etc.

However I'm still a little bit uncomfortable as this translates to a server-side JavaScript environment such as node.js, and more specifically an API written on express.


Take this sample file (lets call it server.js)

var npm_moduleA = require('npmA')({ someInitArg : 'blah' }),
    app = express.createServer();

app.get('/api/foo', function (req, res) {

    var result = npm_moduleA.doSomething();
    res.send(result);

});

app.get('/api/bar', function (req, res) {

    var npm_moduleB = require('npmB')({ someInitArg : 'blah' }),
        result = npm_moduleB.doSomethingElse();

    res.send(result);

});

Questions (assuming this is a high-load site)

  1. What is the lifecycle of npm_moduleA? It gets created at the moment that the server starts, but when (if at all does GC kick in against it) - I'm guessing that it never gets touched because its in the global scope?

  2. In '/api/bar/', should npm_moduleB be deleted after each request? Or should this be left to the GC alone.

  3. Is the global instantiation of npm_moduleA significantly more efficient than repetative the instantiation (and possible deletion) of npm_moduleB?


References

Community
  • 1
  • 1
isNaN1247
  • 17,793
  • 12
  • 71
  • 118

1 Answers1

9

As the node.js won't create and destroy running context for each call, so both npm_moduleA and npm_moduleB will live (in cache) until you kill the server.

In fact no matter where you require the module, it just get a pointer to the module's entry point. it doesn't instance any thing at run time.

here is a example:

index.js

var t = require('./module.js');
t.value = 10;

function test() {
  var t2 = require('./module.js');
  console.log(t2.value);
}

test();

module.js

module.exports = {};

console outputs:

10

In this case just put your require()s at global scope for once. don't do requires in callbacks, because require() has some file name resolving work to do, and it has no difference from require in global scope (in any aspect.)

But if you are going to instance a class new SomeClass(), then where you do it matters.

xiaoyi
  • 6,641
  • 1
  • 34
  • 51
  • Thanks for the reply - you've highlighted an error in the sample code... my requires were suppose to also show the instantiation of a class (so `require('blah')(/* some init args */)` instead of just requiring the source file). I've updated my code, which may affect some of your answer – isNaN1247 May 16 '12 at 09:51
  • 1
    @beardtwizzle: my point still holds, no matter where you require something, it just return a pointer to the cache entry. If you were going to use a function exported in a module, it would live in the cache, and wouldn't be freed until the server die. – xiaoyi May 16 '12 at 10:57
  • @beardtwizzle: -- continues, if your have a static initialization parameter, and the function can be shared during request, then just leave the instance global. It supposed to have better performance, and you can imagine the memory usage is constant at any time (since the requests are responded in serial, try not close a connection, then no other clients will be served). And if your server is really hot, the second pattern will have some performance issue due to create/destroy object and you cannot save a lot memory usage. – xiaoyi May 16 '12 at 11:10