Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What exactly is a TickObject and how prevent it becoming a memory leak?

I've noticed this a couple of times in a few of my scripts. Mainly scripts focusing around array iteration and manipulation.

I keep seeing massive memory leaks that eventually lead to the script running out of memory and dying. After inspection, it seems to be caused by a massive amount of TickObjects being created and not cleaned up.

A bit of reading pushed me to think that TickObject is an internal feature of node to manage asynchronous events. Is that what they're actually used for? Why would they spiral out of control? And how can it be prevented?

In case it helps, heres a dump (warning its around 312mb) https://www.dropbox.com/s/57t70t2igpo8kbi/heapdump-604700798.654094.heapsnapshot?dl=0 of an example where its spiralling out of control.

EDIT:

Managed to simplify the offending code. And strangely looks to be a combo of using process.stdout.write?

var a = Array(100)
    .fill()
    .map(_ => Math.round(Math.random()) ? true : false),
    i = 0;

while (true) {
    a.map(_ => !_);
    process.stdout.write(`#${++i}\r`);
}

Run this and you'll quickly run out of memory. Is this behaviour to be expected? (I assume not) Or is it just weird behaviour with node?

like image 767
raininglemons Avatar asked Jan 07 '23 00:01

raininglemons


1 Answers

Worked it out. The array was a red herring and in reality the actual problem was the process.stdout.write

On each write, an afterWrite clean up function is being queued up as a TickObject each time. As we never leave the Tick/context we're in, this just amass till node explodes. Solution? Make any long/forever running code blocks asynchronous with ticks as well.

var a = Array(100)
    .fill()
    .map(_ => Math.round(Math.random()) ? true : false),
    i = 0;

(function whileLoop () {
    a.map(_ => !_);
    process.stdout.write(`#${++i}\r`);

    process.nextTick(whileLoop);
})();

Victory!

like image 82
raininglemons Avatar answered May 12 '23 02:05

raininglemons