w3c / webtransport

WebTransport is a web API for flexible data transport
https://w3c.github.io/webtransport/
Other
838 stars 51 forks source link

Relative prioritization of streams and datagrams #610

Open afrind opened 1 month ago

afrind commented 1 month ago

Media over QUIC recently merged a PR defining how moq will use priorities (https://github.com/moq-wg/moq-transport/pull/470). The scheme is based on the MoQ object model (track, group, object) and is independent of how that object model is mapped to QUIC or WebTransport constructs (streams and datagrams). It is possible for a MoQ application to specify a track that maps to a stream be given higher priority than a track that maps to datagrams. Jan-Ivar presented at IETF 120 and mentioned that WebTransport now gives priority to datagrams over streams unilaterally, which is incompatible with moq's scheme.

wilaw commented 1 month ago

There is a sendOrder and sendGroup scheme in the WebTransport API which would meet the MoQ requirements, but it only applies to Streams. One way to satisfy the MoQ requirement would be to also put flows of Datagrams into sendGroups of their own and then allow the application to assign the relative priority of those against other stream-based sendGroups. This has been discussed in #451 and #515 but after much discussion was never adopted.

vasilvv commented 1 month ago

I do wonder if we should just give datagrams a sendGroup/sendOrder, that would probably be better than the current wording. Maybe we could even have multiple datagram queues with different priorities.

jan-ivar commented 3 weeks ago

It is possible for a MoQ application to specify a track that maps to a stream be given higher priority than a track that maps to datagrams.

What's the use case? I understand putting audio in datagrams and video in stream-of-streams, and giving audio priority.

WebTransport now gives priority to datagrams over streams unilaterally, which is incompatible with moq's scheme.

I suspect it's incompatible even before https://github.com/w3c/webtransport/pull/604 when things were implementation-defined, but agree we may have to rethink.

Chrome sends all datagrams > all streams whereas Firefox sends all streams > all datagrams. Neither seems moq compatible.

What are moq's requirements?

sendOrder

I think we're talking about weights here (between groups), not send ordering (within groups).

Maybe we could even have multiple datagram queues with different priorities.

Sounds like https://github.com/w3c/webtransport/issues/419.

I'd like to first explore what the incompatibility is. At least for deterministic priorities, we've assumed the app can control the total datagram to stream ratio by how many total datagrams it queues per second. User agents could in theory base their send-buffer dequeuing strategy on its assessment of how quickly datagram send-queues build up, compared with other send-queues.

This was a benefit perhaps of keeping things vague. But how would we capture this in a spec? It would be unfortunate if we grew JS APIs for lack of ability to do so.

afrind commented 3 weeks ago

What's the use case? I understand putting audio in datagrams and video in stream-of-streams, and giving audio priority.

The simplest use-case is that moq control messages go on a stream, which should have higher priority than any media (streams or datagrams). We have also considered having N control streams (and still might).

What are moq's requirements?

moq needs WebTransport to expose a way to set the priority of a datagram in the same priority space as streams (eg: think of it as a 1 packet stream). If that proves too costly, some other way of assigning a flow of datagrams a priority within the same space.

I think we're talking about weights here

moqt doesn't define any weighting (eg bandwidth sharing) schemes at present. There's an algorithm to determine the highest priority "object" to send next, and only that will be sent until it is complete or becomes app limited.

jan-ivar commented 2 weeks ago

Meeting:

  1. consider an API to associate a datagram writable to a send group
  2. consider constructor to create additional datagram writables
jan-ivar commented 2 weeks ago

@wilaw and I were discussing an example to see if this would work (feel free to post your own):

Example 1. I'm sending:

  1. 100 GB file "A"
  2. 100 GB file "B"
  3. A light control bidi stream "C"
  4. An infinite flow of datagrams "D"

What should happen under congestion? I want C to starve everything else if need be Then I want D to be sent ahead of both A and B (but not C)

Today this won't work: D will be sent ahead of everything else (then A, B and C get ⅓ of what's left)

API option 1: wt.datagrams.sendGroup = S; wt.datagrams.sendOrder = n

Here, C would starve D would starve A and B if needed.

jan-ivar commented 2 weeks ago

The above puts different flows in the same sendGroup, breaking any notion that one was supposed to create a sendGroup per flow. Maybe that's fine since one clearly can, but it might come back to bite us.

E.g. two sendOrder-using stream-of-streams flows in the same sendGroup would yet again be forced to lockstep their increment/decrement strategies (why we introduced sendGroups in the first place).

If the main objection to https://github.com/w3c/webtransport/issues/419 was "weights" being relative, we can replace it with strict priority:

API option 2: wt.datagrams.strictPriority = 1; S.strictPriority = 2

Here datagrams acts as its own inherent send group (we can still consider constructing multiple).

jan-ivar commented 5 days ago

API option 1 doesn't work because datagrams don't fit in send groups (sendGoup.getStats() produces WebTransportSendStreamStats which datagrams don't have).

API option 2 seems cleaner to me:

const a = await wt.createUnidirectionalStream();
const b = await wt.createUnidirectionalStream();
const s = wt.createSendGroup();
s.strictPriority = 2; // new
const c = await wt.createBidirectionalStream({sendGroup: s});
const d = wt.createDatagramsWritable(); // new
d.strictPriority = 1; // new

await readableDatagrams.pipeTo(d);

Less rope for web developers.

jan-ivar commented 4 days ago

Meeting:

martinthomson commented 4 days ago

The idea was to treat datagram writeables as streams for the purposes of prioritization. There would need to be differences in other aspects, like stats. My suggestion would be to expand the getStats to include datagram stats separate from stream stats.

afrind commented 3 days ago

The idea was to treat datagram writeables as streams for the purposes of prioritization.

I was recently looking at modifying the mvfst QUIC API to add datagram prioritization and came to a similar idea.