help
help copied to clipboard
Nodejs Buffer performance (v14)
- Node.js Version: 14
- OS: Ubuntu 18.04
- Scope (install, code, runtime, meta, other?): runtime
- Module (and version) (if relevant): Built-in Buffer
One of the projects that I work on makes heavy use of Buffer for a binary communications protocol. Nearly all of the messages are less that 256 bytes in length. After doing some reading on Buffer, I understand that internally the Buffer object does not allocate storage space via the V8 engine but instead utilizes a cache. This improves performance for obvious reasons. However, it appears that Buffer reuse is often overlooked and not easily supported. As a result, it is common to see many thousands of Buffer objects being allocated in the natural course of network protocol communications every second. The Buffer objects themselves are allocated via new. As a result, it appears that it is left up to the V8 garbage collector to reclaim these Buffer objects. Looking for someone with some in-depth knowledge of how Buffer objects are handled by nodejs and to help shed some light on potential performance issues here.
Buffer objects aren’t cached, they are pooled – and it sounds like you’re looking for a way to cache them, so that they can be re-used instead of being fully deallocated once they are garbage collected?
The way that V8 works internally, I don’t think this would be easy to do. Node.js does provide its own ArrayBuffer allocator to the JS engine, and it could decide not to actually free memory when its reference count drops to zero and instead to keep the memory around for later re-use. However, that would seem more like the job of the library that provides the native allocation functions.
For small buffers, that’s probably not worth it anyway – there’s also going to be overhead for each ArrayBuffer and TypedArray object itself.
You may be able to do meaningful buffer re-use through the WeakRef API, but I wouldn’t guarantee it.
@addaleax Thank you for the detailed response. To further clarify, when buffers are allocated via the API (i.e. Buffer.alloc(size)), the returned buffer is actually from a pool of buffer objects. When unreferenced, they are then returned to the pool. As a result, no garbage collection is being performed until the pool itself is cleaned up. The buffer pool has some high/low water marks where it may grow and shrink the pool accordingly. Where shrinking the pool would involve unreferencing the Buffer object completely thereby allowing V8 to garbage collect. Is this more or less correct?
@davidchappelle Assuming that you’re describing an idea for how it should be, and not the current state of things, yes.
(For the current state of things: The pool is fixed-size, there are no high/low watermarks, and no garbage collection involvement or buffer reuse at all.)
It seems there has been no activity on this issue for a while, and it is being closed in 30 days. If you believe this issue should remain open, please leave a comment. If you need further assistance or have questions, you can also search for similar issues on Stack Overflow. Make sure to look at the README file for the most updated links.
It seems there has been no activity on this issue for a while, and it is being closed. If you believe this issue should remain open, please leave a comment. If you need further assistance or have questions, you can also search for similar issues on Stack Overflow. Make sure to look at the README file for the most updated links.