apache / apache/opendal

new feature: reduce copies and runtime crossings in Node.js streaming reads

Open
#8,250 0 comments 1 reaction 0 assignees View on GitHub
enhancement
Dominant language
Rust
Stars
5.4k
Forks
825
Avg merge
1d 14m
Merged PRs (30d)
127

Description

### Feature Description

Provide an ownership-aware native chunk path for Node Readable so stream consumers can avoid copying every payload into a separately allocated JS destination.

### Problem and Solution

The native Reader currently fills a JS-provided Buffer through AsyncRead. The public Readable wrapper also allocates its destination per pull. This incurs a payload copy at the Rust-to-JS boundary plus wrapper allocation/initialization. Small native completions additionally incur promise/runtime crossings.

An additive owned-chunk path could return native-backed data with an explicit owner/finalizer and feed it into the existing Readable wrapper. Bounded aggregation may help fragmented input, but must balance fewer crossings against added copies, latency, and memory. Preserve the existing BYOB API.

Acceptance criteria:
- Handle segmented buffers, partial reads, backpressure, retained JS chunks, cancellation, errors, and worker teardown.
- Account for external memory and release native owners correctly.
- Compare natural sequential GetObject-style consumption using the same sink; measure copy volume, CPU, first-byte latency, throughput, and memory.
- Preserve mutable-buffer safety: this request does not remove the upload snapshot copy, whose data may remain needed after write returns for buffering and retries.

### Additional Context

[Native async Reader](https://github.com/apache/opendal/blob/b6cf44f7b8a1523409e0e998e478c996ac970f03/bindings/nodejs/src/lib.rs#L1024); [Public Node wrappers](https://github.com/apache/opendal/blob/b6cf44f7b8a1523409e0e998e478c996ac970f03/bindings/nodejs/index.cjs#L1)

Related to #7909, but distinct: that request lets a backend fill caller-owned memory; this request lets Node adopt native-owned output for its stream. It can be evaluated without first adding a new backend read capability.

Source references are pinned to `b6cf44f7b8a1523409e0e998e478c996ac970f03`. This request describes an optimization opportunity; it does not claim a measured end-to-end speedup.

Contributor guide

Open the contributing guide

Research direction

Read bindings/nodejs/src/lib.rs around the native async Reader and bindings/nodejs/index.cjs for the public Readable wrapper, then trace how reads, ownership, cancellation, and backpressure cross the boundary. Done means an additive owned-chunk path preserves BYOB and mutable-buffer safety, releases owners correctly, handles the listed edge cases, and compares copy volume, CPU, latency, throughput, and memory using the same sink.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, rust
Domain
api, backend, performance
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.