Search code examples
node.jsmultithreadingmemory-managementgarbage-collectionv8

Why call AdjustAmountOfExternalAllocatedMemory


Why should external code call v8::Isolate::AdjustAmountOfExternalAllocatedMemory, formerly known as v8::V8::AdjustAmountOfExternalAllocatedMemory and together also known as NanAdjustExternalMemory?

I see some bits of documentation on the web that these functions exist, and that they somehow help ther garbage collector. But how? Why? What repercussions are to be expected if some external code doesn't call these? In a Node.js module which makes use of asynchroneous execution, is it worth the effort to communicate changes in memory allocation from the worker threads back to the v8 thread where this function can be safely called? Why should anyone care how much memory the external code is using? And if there is a good reason, should I try to provide fine-grained updates for every malloc and free, or should I only call the function every once in a while, when the situation changes significantly?


Solution

  • You should only update it for memory that is kept alive by JavaScript objects. I.E. you have SetInternalField in a javascript object that points to C memory it owns.

    This doesn't appear to be the case for you as you say:

    is it worth the effort to communicate changes in memory allocation from the worker threads back to the v8 thread where this function can be safely called

    Whatever memory your workers allocate, cannot be kept alive by some 'separate v8 thread' because an isolate can only be executed by a single thread. So it cannot be keeping alive any memory your other threads are allocating, so it is irrelevant.


    In general you want to call this function because it will force v8 to do global GC more often, which it normally avoids doing at all costs. E.g. If you have 1000 dead javascript buffers each reserving 20MB, you have ~20GB of garbage while V8 thinks you only have some 20kb of garbage and thus won't try to GC anything. If you then told V8 that there is 20GB of external memory (AdjustAllocatedMemory(20 * 1024 * 1024 * 1024)), it would trigger a global GC, which would GC the JavaScript buffer objects, which would call their finalizers, where you would free() the 20MB buffers, which would free 20GB of memory.