Skip to content

readable.readv(size) to reduce memory copies #20560

@guymguym

Description

@guymguym
  • 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:

  1. 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.

  2. 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 copy Buffer.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:

  1. readv(size) - same as read(size) but returns an array of buffers so avoids concat altogether.

  2. 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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    feature requestIssues that request new features to be added to Node.js.streamIssues and PRs related to the stream subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions