Safe to drop a Buffer before GC? #1444
Replies: 4 comments 3 replies
-
@overlookmotel sorry, I missed this discussion. Maybe this API will help https://nodejs.org/api/n-api.html#napi_open_handle_scope. I'd like to investigate how to integrate this API in this scenario |
Beta Was this translation helpful? Give feedback.
-
Thanks for coming back. I'll look into napi_open_handle_scope. One other question in meantime: Is the |
Beta Was this translation helpful? Give feedback.
-
Just a note, while I continue to investigate this. The reason for my observation of memory not getting freed in a tight loop is not that GC doesn't run, but that the finalize callback is scheduled to run with |
Beta Was this translation helpful? Give feedback.
-
I've looked into As far as I can see, that API is designed to solve a different problem - telling V8 to keep a handle for a In my example, the default is correct. V8 knows when it can GC the buffer. The problem is that either:
In my example above, (2) is the most likely explanation. I wonder if @Brooooooklyn Does that sound correct to you? If so, do you think it'd be useful to include this in napi-rs's API somehow? Like adding a |
Beta Was this translation helpful? Give feedback.
-
If you create an
ArrayBuffer
in Rust and pass it to JS, is it safe to drop its backing memory before the JS garbage collector collects the buffer if you know it's no longer in use?My use case is this: I'm running a series of calls to a synchronous NAPI function which returns a large buffer. That buffer is then used (again, synchronously) in JS, and then discarded. The program does that over and over.
If I make all these calls without any ticks in between, JS garbage collector never gets a chance to run, and memory usage explodes. e.g.:
I'm wondering if something like this is possible:
Rust side: (assumes that there's only ever 1 buffer in play at a time)
In theory this makes some sense. We know that the buffer is no longer referenced before the garbage collector does, so why not free it early?
And the above example seems to work - memory consumption is massively reduced.
However, is it safe? The following chain of events is very likely:
create_buffer()
creates a buffer, stored at memory address X.destroy_buffer()
drops buffer's backing memory.create_buffer()
called again. Allocator reuses previously freed memory, and 2nd buffer also has memory address X.Is that likely to go horribly wrong?
Beta Was this translation helpful? Give feedback.
All reactions