Re: [streams] First draft at tee algorithms, for critique (#302)

@wanderview thanks for jumping into this!!

1) Yes, I was just starting with an algorithm other specs could reference, but it'd make great sense to define `ReadableStream.prototype.tee()` that returns `TeeReadableStream(this)` and `ReadableByteStream.prototype.tee()` that returns `TeeReadableByteStream(this)`.

2) Hmm, I don't quite follow this. Could you explain more? In particular, I don't think we want to allow transferring the contents of a stream---the entire point here is to actually produce two copies, such that both can be operated on in separate threads at the same time without affecting each other.

3) Here you go, keeping in mind that ReadableByteStreams are still a bit in-our-heads instead of explained-on-paper:

```js
const [branch1, branch2] = SpeculativeTeeReadableByteStream(rbs);

const reader1 = branch1.getReader({ feedBuffers: true });
const reader2 = branch2.getReader({ feedBuffers: true });

const view1 = new Uint8Array(512);
const view2 = new Uint8Array(1024);

reader1.read(view1).then(({ value, done }) => {
  // value uses same backing memory as view1, via transferrence
  // we were able to pass view1 directly to the `reader` for `rbs`
});
reader2.read(view2).then(({ value, done }) => {
  // value uses same backing memory as view2
  // however, how the data gets there was a bit different, and less efficient:
  // once rbs was finished with view1, we cloned it into a new buffer that we enqueued
  // into branch2's internal queue. then, the call to reader2.read(view2) caused us to
  // copy the queued buffer into the backing memory used by view2.

  // hmm, there's a redundant copy here :-/ ... might be able to avoid ...
});
```

> I guess I'm thinking of how our native C++ stream does tee'ing when I read this. Our nsPipe class internally maintains a single buffer. Every tee'd stream then has its own cursor into that shared buffer. The buffer is split up into segments and as the slowest reader finishes a segment it is free'd back to the allocator. I think this is more efficient then duplicating buffers in two queues, etc.

Hmm, very interesting. It sounds like the tee'd streams are not really of the same "type" as the original stream? That is, they are not very general purpose, but instead there's a cooperation between the branches and the original, where the branches largely consist of a cursor and not much else? The duplication is not really avoidable when dealing with the no-data-races-in-JS mandate. But I'll try to think on this more to see if there's something we can learn.

---
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/pull/302#issuecomment-82972347

Received on Wednesday, 18 March 2015 13:32:56 UTC