Re: [streams] rsReader.readBatch(numberOfChunks)? rbsReader.read(view, { waitUntilDone: true })? (#320)

First, let me say that I regret making this feedback at such a late stage.  The read() method became async a while ago and I really should have said something then.  I apologize for not being more involved earlier.

That being said, I don't think we can ignore this kind of data.  If we're going to fix it we should do it sooner rather than later.

While I could debate you point-for-point, I'd instead like to discuss the idea that every chunk is directly tied to an equivalent amount of I/O.  I think this a reasonable position for byte-oriented streams, but it seems ReadableStream is also designed to support message-oriented streams.

I think message-oriented streams can very easily produce many chunks from relatively little I/O.  Allow me to lay out an example:

Consider a framework or application that wants to modularize its software.  To do this it connects the modules with message streams.  The framework is designed such that each stream chunk is a Message object.

Now consider that the framework has the ability to send and receive Message objects over the network.  Or it is loading Message objects from a file.  Lets say the wire protocol for a Message takes on average 128 bytes.

Now consider a MessageParserTransform.  This is a ReadableStream/WritableStream pair that accepts ArrayBuffer chunks and produces Message objects.  One ArrayBuffer may produce many Message objects.

If a MessageParserTransform consumes a 4096-byte buffer, it will produce 32 Message objects.

Based on the benchmark, reading these 32 message objects out of MessageParserTransform will take over 7ms on a mobile device.  This is 7ms of time added on top of the I/O.

Now, you may be saying to yourself "but those 7ms can happen while you're doing more I/O".  That's true, but it only helps solve the bandwidth problem.  Unfortunately, people also care about latency.  In this case the async scheduling required by read() is adding unavoidable latency.

This is just one example, but I hope it demonstrates a realistic use case for sending larger numbers of chunks through a stream without increased external I/O.

Finally, I'd just like to clarify that I'm now advocating for a sync read with a ready promise like was previously spec'd.  Given these numbers I'd like to see sync be the default.

I'm unsure about sync vs async .write() at this point.  It seems we expose a state which could be checked synchronously, but its a bit inconvenient to require a second statement to detect back pressure.

---
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/issues/320#issuecomment-91437183

Received on Friday, 10 April 2015 05:44:18 UTC