-
-
Notifications
You must be signed in to change notification settings - Fork 34.2k
Description
- Version: v10.0.0
- Platform: Darwin
- Subsystem: stream
This is a feature request:
Currently, a readable stream in paused mode (non-flowing) allows only read([size]) to consume data from the internal buffer list:
-
read()(without size) returns a buffer in any size, therefore always copyless, but using it for decoding specific data structures is hard and will require coalescing buffers and concatenating or unshift back remains when received too much. -
read(size)will return null if not enough bytes, otherwise it will extract the requested size from the internal buffer list. This extraction (fromList(n, state)at https://github.com/nodejs/node/blob/v10.0.0/lib/_stream_readable.js#L1047) will use memory copyBuffer.concat()when the size involves multiple buffers.
The problem is that the behavior from read(size) is not allowing a consistent performance since in some cases we will incure buffer allocation + copy, and in others we just use slicing.
These are two ways to get a more consistent performance of readable streams:
-
readv(size)- same asread(size)but returns an array of buffers so avoids concat altogether. -
read(buffer)will return null if not enough bytes are available, otherwise it will read directly into the provided buffer and return it. This avoids allocating new buffers, but will always copy from the internal buffer list to the preallocated buffer. This is useful when decoding small fixed size structures such as packet headers in which the copy is less noticeable, but the number of allocations is affecting GC.
Clearly readv() is more robust than read(buffer) and might suffice, but the latter is a simple way to avoid unwanted allocations or use buffer pools.
Would be great to get your thoughts if this is worth making a PR.
Thanks!