Recently I was working on an experimental Buffer pool implementation based on FinalizationGroup API (see #30683) and encountered a weirdness that I'd like clarify. It seems that node doesn't free memory when FinalizationGroup is used to track Buffers (as "holdings") under certain conditions. This issue may be related with off-heap memory allocator or OS memory behavior, but I'd like to confirm that.
Here is the most simple reproducer that I could find:
'use strict';
const fg = new FinalizationGroup(finalizer);
// 8 ticks, 1GB per each => 8GB total
const ticks = 8;
const bufsPerTick = 1024;
const size = 1024 * 1024;
let slices = [];
let tick = 0;
setInterval(() => {
tick += 1;
if (tick === ticks) console.log('Registered all slices');
if (tick > ticks) {
slices = [];
return;
}
slices = [];
for (let i = 0; i < bufsPerTick; i++) {
const buf = Buffer.alloc(size);
const slice = buf.slice();
slices.push(slice);
fg.register(slice, buf);
}
}, 500);
let finalized = 0;
function finalizer(iter) {
for (const _ of iter) {
finalized += 1;
if (finalized === ticks * bufsPerTick)
console.log('All finalizer callbacks are triggered');
}
}
When this script is run under --harmony-weak-refs flag, node process consumes about 2GB of physical memory on my machine (and about 2.5GB of virtual memory) and that value doesn't decrease even after 10 minutes.
On the other hand, if you comment the fg.register(slice, buf); line, you'll see that resident memory consumption eventually goes down to ~32KB (virtual is ~600MB).
Once again, I'm not sure if that's a bug, but I'd like to understand the reason of such behavior.
Recently I was working on an experimental Buffer pool implementation based on FinalizationGroup API (see #30683) and encountered a weirdness that I'd like clarify. It seems that node doesn't free memory when
FinalizationGroupis used to trackBuffers (as "holdings") under certain conditions. This issue may be related with off-heap memory allocator or OS memory behavior, but I'd like to confirm that.Here is the most simple reproducer that I could find:
When this script is run under
--harmony-weak-refsflag, node process consumes about 2GB of physical memory on my machine (and about 2.5GB of virtual memory) and that value doesn't decrease even after 10 minutes.On the other hand, if you comment the
fg.register(slice, buf);line, you'll see that resident memory consumption eventually goes down to ~32KB (virtual is ~600MB).Once again, I'm not sure if that's a bug, but I'd like to understand the reason of such behavior.