Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement "Bring Your Own Buffer" constructs for ReadableStream #3918

Open
Tracked by #3920
oleiade opened this issue Aug 28, 2024 · 0 comments
Open
Tracked by #3920

Implement "Bring Your Own Buffer" constructs for ReadableStream #3918

oleiade opened this issue Aug 28, 2024 · 0 comments
Labels

Comments

@oleiade
Copy link
Member

oleiade commented Aug 28, 2024

Description

As part of our effort to make handling large amounts of data more efficient, k6 has introduced support for the WebAPI ReadableStream construct as part of its k6/experimental/streamsmodule. While it’s already possible to handle binary data using this construct, it is neither the most convenient nor the most efficient way to do so.

To better accommodate binary data, we propose to implement the ReadableStreamBYOBReader and its ReadableByteStreamController and ReadableStreamBYOBRequest counterparts. These components allow binary data to be read from a stream into a user-provided buffer in a zero-copy fashion, improving performance and control.

Practical Benefits:

  • Improved Memory Control: This feature allows precise control over how much memory is allocated for reading binary data by reusing user-defined buffers.
  • Enhanced Efficiency: We eliminate redundant copies by reading data directly into user-provided buffers, reducing CPU overhead and garbage collection.
  • Better Buffering Management: Users can manage the size of the buffers, allowing for optimized reads when processing large files or data streams.
  • Explicit Binary Handling API: The BYOB reader offers a clear and explicit API for managing binary data, making it easier for developers to handle low-level data processing tasks.

Usage in practice

To read data from a stream, a user needs to instantiate (define) a stream, get a "reader", and call read on that reader repeatedly until the stream is closed or cancel.

Without BYOB reader

Currently, this is how reading from a stream can be achieved. Whenever .read is called, the value received is a new copy of the chunk produced by the stream.

// ... Some Stream definition ...

// Obtain and lock a reader to the stream
const reader = myPredefinedStream.getReader();

try {
    // Read and process each item from the stream
    while (true) {
      const { done, value } = await reader.read();
      if (done) {
        break;
      }

      console.log(value);
    }
  } catch (error) {
    console.error('Stream reading failed:', error);
  } finally {
    reader.releaseLock();
  }

With BYOB reader

With the BYOB reader, the read method takes as an argument a view of a user-supplied buffer into which data is read directly, bypassing the need for additional memory allocations. The value returned is a view over the same buffer, populated with the new data.

// ... Some Stream definition ...

// Obtain and lock a reader to the stream in BYOB mode
const reader = myPredefinedStream.getReader({ mode: "byob" });

// Predefine a buffer to read data into
let intoBuffer = new Uint8Array(200); // A typed array view over an ArrayBuffer

try {
    // Read and process each item from the stream
    while (true) {
      // Use the buffer to store the read content directly, without internal copies
      const { done, value } = await reader.read(intoBuffer);
      if (done) {
        break;
      }

      // The returned `value` is a view pointing to the `intoBuffer` containing the new data
      console.log(value);
    }
  } catch (error) {
    console.error('Stream reading failed:', error);
  } finally {
    reader.releaseLock();
  }

Suggested Solution (optional)

No response

Already existing or connected issues / PRs (optional)

#2974
#2978
#3666

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant