0
setInterval(() => {
    var mem = process.memoryUsage();
    console.info("Memory used: ", mem.heapUsed.toString().replace(/\B(?=(\d{3})+(?!\d))/g, " "));
}, 1000);

server.get("/", function(req, res, next) {
    var test = new Array(1e7);
    test = null;
    res.send(200);
    next();
});

The interval timer keep reporting a more or less steady memory usage, but then after I make a request to the restify-endpoint, it goes up by 80 MB (natural as I assign a 10 million element array), but then it remains there. Does this mean the large array is still in memory even after I assign null to the variable?

Memory used:  82 645 408
Memory used:  82 647 240
Memory used:  82 649 072
Memory used:  82 650 904
Memory used:  82 652 736
Memory used:  163 126 464
Memory used:  163 136 128
Memory used:  163 137 968
Memory used:  163 139 808
Memory used:  163 141 648
Memory used:  163 143 488
Memory used:  163 145 328

This is a very simplified example, the end goal is to avoid objects used in api endpoints remaining in memory when they are no longer being used.

henit
  • 1,150
  • 1
  • 12
  • 28
  • 1
    test = null; will not guarantee you that its been garbage collected. – Thalaivar Dec 29 '15 at 09:58
  • 1
    I read that it is garbage collected when there is no references left to it. How can there be any more references to the variable in this case? – henit Dec 29 '15 at 10:00
  • If your objects aren't being referenced anywhere, then its fine and it makes sense... – Thalaivar Dec 29 '15 at 10:01
  • No reference. And that should not matter as the function is a closed context? Unless restify does some magic here – henit Dec 29 '15 at 10:05

1 Answers1

0

If you check out this article on V8 garbage collection you will see this:

Large-object-space: This space contains objects which are larger than the size limits of other spaces. Each object gets its own mmap'd region of memory. Large objects are never moved by the garbage collector.

I don't know the specifics of what constitutes a "large object," but an array of 10 million seems like it might fit the description. The question is, if large objects are never moved by the garbage collector then how are they cleaned up? I haven't found the answer to that yet.

However, if you fire up node in a terminal and then repeatedly run this command

var myarr = new Array(1e7)

you will see that memory does increase, but only to a certain point. I found that as soon as memory use went over 500MB then some kind of garbage collection happened and the memory use dropped back down to 251MB. So, while it may look like your large array never goes away V8 will, in fact, do something about it at some point.

HeadCode
  • 2,770
  • 1
  • 14
  • 26
  • I see. Then how can I make sure an end point in an API running on Node (Restify/Express etc) does not keep created objects in memory from every request? Any way to track if a specific object is garbage collected or still remain in memory? – henit Jan 04 '16 at 12:37
  • @henit I don't think you should waste your time worrying about specific objects. Just make sure you null out any global variables if you need to, otherwise in the example you gave above those objects will go out of scope and be automatically garbage collected at some point. Try it yourself. Keep hitting the request and watch the memory allocation build and then go back down. Your real worry should be if you are allocating large objects in closures. – HeadCode Jan 04 '16 at 16:39