Subject: Extensible Priorities and Reprioritization

From: Lucas Pardue <[email-masked]>
Date: Fri, 5 Jun 2020 00:33:06 +0100

Hello folks,

The Extensible Priorities draft has an open issue on the topic of
reprioritization [1] and the May 2020 HTTP Interim session [2] pivoted
towards it. The discussion highlighted that reprioritization is something
we need to get to the bottom of in order to unblock progressing this draft.

Our definition of the reprioritization feature is purposefully narrow, but
the frame-related mechanics cause complications for implementations. One
option on the table is to take reprioritization out of the critical path of
draft-ietf-httpbis-priority by extracting the text to leave a simpler
definition of just the scheme and the Priority header signal. The extracted
text could be put in a separate I-D, reworked, replaced, or dropped
altogether. The choice of action is ultimately up to the WG, so that is why
we’re sending this email.

Removing reprioritization from draft-ietf-httpbis-priority sounds pretty
drastic but in all the work that’s got us here, we’ve struggled to find
data that backs up its efficacy.

Reducing Extensible Priorities to its core, clients issue priority signals
(U and I) based on the expectation that the server, if possible, will
transmit responses in the order of their urgency and request order
(inferred by stream ID). Reprioritization is a client sending a subsequent
signal (U’ and I’) that modifies the priority of in-flight responses.
Reprioritization is not:

   -

   Sending a batch of requests and signalling the desire for later requests
   to be sent before earlier ones. By design, that is supported using urgency.
   -

   Purposeful ordering of requests to meet a priority objective. This a
   client implementation choice.
   -

   Aborting requests or responses that are in flight. By design, that is a
   function provided by HTTP/2 or QUIC streams that is actioned by
   implementation choice.
   -

   Manipulating a dependency tree through the lifetime of a connection. By
   design, that is not required.
   -

   Any other mechanisms to adjust the server’s scheduling of response data.
   That is out of scope.

We’d be very interested to hear from people who support keeping
reprioritization and can provide data, directly or indirectly, that the way
it is applied in the extensible priority scheme provides tangible benefits.
Data to the opposite effect is also of interest.

Cheers

Kazuho and Lucas

Extensible Priorities Editors

[1] - https://github.com/httpwg/http-extensions/issues/1021

[2] -
https://github.com/httpwg/wg-materials/blob/gh-pages/interim-20-05/minutes.md#priorities

---

From: Yoav Weiss <[email-masked]>
Date: Fri, 5 Jun 2020 10:14:04 +0200

On Fri, Jun 5, 2020 at 1:36 AM Lucas Pardue <[email-masked]>
wrote:

>    Sending a batch of requests and signalling the desire for later
>    requests to be sent before earlier ones. By design, that is supported using
>    urgency.
>    -
>
>    Aborting requests or responses that are in flight. By design, that is
>    a function provided by HTTP/2 or QUIC streams that is actioned by
>    implementation choice.
>    -
>
>    Manipulating a dependency tree through the lifetime of a connection.
>    By design, that is not required.
>    -
>
>    Any other mechanisms to adjust the server’s scheduling of response
>    data. That is out of scope.
>
>

Chromium is re-prioritizing image requests. Images are sent with low
priority and in-viewport images are later re-prioritized (once
layout happens and the browser knows they are actually in the viewport).
IIRC +Bence Béky <[email-masked]> implemented that re-prioritization for
H2, and may have data regarding its impact from the launch. Also CCing +Tarun
Bansal <[email-masked]>, as he may be aware of data to its efficacy.

Note that any such data regarding H2 would be biased by current H2
implementations and their challenges
<https://blog.cloudflare.com/better-http-2-prioritization-for-a-faster-web/>
with buffer bloat. So I'd tend to trust test cases/examples from known
good-actors more than internet-wide data that's more likely to be watered
down with other issues.

What's the timeline for us to provide supporting data and/or tests cases in
order to keep re-prioritization in?

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 5 Jun 2020 15:11:24 +0100

Hey Yoav,

On Fri, Jun 5, 2020 at 9:14 AM Yoav Weiss <[email-masked]> wrote:

> IIRC +Bence Béky <[email-masked]> implemented that re-prioritization
> for H2, and may have data regarding its impact from the launch. Also CCing +Tarun
> What's the timeline for us to provide supporting data and/or tests cases
> in order to keep re-prioritization in?
>

Thanks for bringing up the challenges with H2, presenting data with this in
mind seems important. Prioritization considerations wrt server-side TCP
buffering [1] apply not only to reprioritization but preemption (the case I
described as a bunch of requests where later requests are more urgent than
earlier ones).

Picking specifically on browsers, they have many options at their disposal
to improve page load metrics. I think it would be useful to understand how
big a role reprioritization plays in that. Maybe the WG would benefit from
a distilled test case that can used to exercise reprioritization. For
instance, is there a way to script and/or create a reproducible test for
viewport changes?

In terms of timeline, that's a bit tricky to answer and I assume the WG and
chairs might have some opinions. To put the question back to you, is this
data you have close to hand or are we talking weeks or months of
experimental data gathering subject to engineering work or product release
cycles?

I'll close with a curveball idea: IIUC the viewport case, the dilemma is
that when a browser makes the first set of requests, it is very unlikely to
have the information required to know what is in-viewport vs.
out-of-viewport. So for some types of resource you *always* want to
promote/demote the resource's importance when discovering this, but for
other types of resource you *never* need to. Could you make this a more
explicit signal? I.e. rather than creating a general-purpose
reprioritization mechanism that is applicable in a fraction of cases, one
could create a "viewport/layout change" signal that tackles this specific
case? For instance a frame called VIEWPORT that contains a boolean flag and
a set of stream IDs that identify the affected requests.  Such a thing
would suit being defined in an independent I-D.

Cheers,
Lucas

---

From: Patrick Meenan <[email-masked]>
Date: Fri, 5 Jun 2020 10:40:49 -0400

If you're looking for a distilled test case, my HTTP/2 prioritization test
page <https://github.com/pmeenan/http2priorities/tree/master/stand-alone>
used for the https://ishttp2fastyet.com prioritization support tracking.
It loads a bunch of images "below the fold" and then after they start
loading it injects 2 images (one after the other) into the viewport.

Building a whole separate "VIEWPORT" scheme that is browser-specific feels
a bit like punting on the problem and effectively killing it, particularly
since most of the drive behind simplifying prioritization was for the
browser use case anyway.

What are the difficult points around implementing the current
reprioritization plans? Is it a sequencing problem with streams and
out-of-band changes? Would it help if the priority change was actually a
stream-level message and specifically changed just the urgency of the
requested stream (with any server-side headers overriding even the changed
urgency)?

On Fri, Jun 5, 2020 at 10:15 AM Lucas Pardue <[email-masked]>
wrote:

> Thanks for bringing up the challenges with H2, presenting data with this
> in mind seems important. Prioritization considerations wrt server-side TCP
> In terms of timeline, that's a bit tricky to answer and I assume the WG
> and chairs might have some opinions. To put the question back to you, is
> this data you have close to hand or are we talking weeks or months of

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 5 Jun 2020 16:55:27 +0100

Hey Patrick,

On Fri, Jun 5, 2020 at 3:41 PM Patrick Meenan <[email-masked]> wrote:

> If you're looking for a distilled test case, my HTTP/2 prioritization
> test page
> <https://github.com/pmeenan/http2priorities/tree/master/stand-alone> used
> for the https://ishttp2fastyet.com prioritization support tracking.  It
> loads a bunch of images "below the fold" and then after they start loading
> it injects 2 images (one after the other) into the viewport.
>

It's a good test case but I wonder how it directly translates to
reprioritization frames. I think understanding specific wire behaviour in
H2 and mapping that into Extensible priorities is the key to figuring out
if PRIORITY_UPDATE frames are required. I suspect that in H2 and chrome,
your test case triggers an implicit tree reshuffle because the new request
is inserted somewhere with an explicit dependency.  Or maybe it triggers a
whole set of PRIORTY frames that shuffle the tree? How does the behaviour
of other implementations look on the wire?

That said, I think things play out differently in Extensible priorities.
The "below the fold" images can be requested at an urgency of N, the
injected images are requested later at a higher urgency between N-1 and 0.
A server that follows the specification's recommendations will pass your
test; no reprioritization frames are required to be sent.

> since most of the drive behind simplifying prioritization was for the

Point taken. Although I will clarify that some of the drive toward a header
was to expose more control to web developers. We might also want to
consider how this scheme's reprioritization feature would or would not be
exposed. That might limit it's usefulness even further.

> requested stream (with any server-side headers overriding even the changed

The H2 request/response exchange sequence [1] requires the final frame in
the sequence to bear the END_STREAM flag, which closes the send side of the
stream and prevents any more frames being sent. Furthermore, see the thread
Mike Bishop started about H2's lack of grease and the impact on extension
points [2], support for extension frames on request streams might cause
connection failures. Since then Cloudflare has fixed a regression that
addresses this problem but I'm unsure of the status in the wider ecosystem.

For the above reasons, restricting PRIORITY_UPDATE to the control stream
(H2 stream 0) is a safe deployable approach. But it introduces cross-stream
referencing and that requires some careful consideration for
implementations, such as buffering and resource usage.

Channeling the WG discussion, I think it is reasonable to ask if clients
are interested in implementing the reprioritization feature. Because if we
don't exercise it with running code, it is hard to iron out the issues and
capture the necessary detail in the document. As evidenced by the problems
found in H2 stacks after they widely shipped.

Cheers
Lucas

[1] - https://tools.ietf.org/html/rfc7540#section-8.1
[2] - https://lists.w3.org/Archives/Public/ietf-http-wg/2019OctDec/0047.html

---

From: Yoav Weiss <[email-masked]>
Date: Mon, 8 Jun 2020 11:53:20 +0200

On Fri, Jun 5, 2020 at 5:55 PM Lucas Pardue <[email-masked]>
wrote:

>> <https://github.com/pmeenan/http2priorities/tree/master/stand-alone>
>> used for the https://ishttp2fastyet.com prioritization support
>> tracking.  It loads a bunch of images "below the fold" and then after they
>> start loading it injects 2 images (one after the other) into the viewport.
>>
>
>> Building a whole separate "VIEWPORT" scheme that is browser-specific
>> feels a bit like punting on the problem and effectively killing it,
>> particularly since most of the drive behind simplifying prioritization was
>> for the browser use case anyway.
>>
>
> Point taken. Although I will clarify that some of the drive toward a
> header was to expose more control to web developers. We might also want to

To clarify, the main use of reprioritization today is for early discovered
resources, which conditions change during the page load, after their
initial requests were already emitted.
The most prominent example is in-viewport images, which requests often go
out before layout happens.
But one can also think of e.g. stylesheets which use the async pattern
<https://www.filamentgroup.com/lab/load-css-simpler/> or low-priority
scripts, which priority suddenly increases (after the request for them is
sent) due to user interaction.

> are interested in implementing the reprioritization feature.
>

I'll let +Bence Béky <[email-masked]> & +Ian Swett <[email-masked]> weigh
in on this question, as they are more likely than me to actually do the
work involved.

> Because if we don't exercise it with running code, it is hard to iron out
> the issues and capture the necessary detail in the document. As evidenced
> by the problems found in H2 stacks after they widely shipped.
>
> Cheers
> Lucas
>
>
> https://lists.w3.org/Archives/Public/ietf-http-wg/2019OctDec/0047.html
>
>

---

From: Eric Kinnear <[email-masked]>
Date: Mon, 08 Jun 2020 17:46:00 -0700

Hi all, 

As another datapoint, Safari (and URLSession for general HTTP use outside the browser) use reprioritization to update the incremental flag.

One place where we do that update is during a download in Safari: since some responses are displayed and some responses are downloaded, we don’t know upfront if we’re going to be rendering the content onscreen or putting it in the downloads list. More generally, we support the concept of “fetch the response for this request” as well “download this resource to some path on disk for me to deal with later”, and switching between them causes us to signal whether we are [no longer] interested in incremental delivery of the resource.

Unfortunately, we don’t currently have any numbers to share about efficacy here, but it does seem as though the ability to update the value that we sent is key in supporting an API that allows both directions of update: 
- Clients can defer updates to a resource, knowing that they can “re-request” such incremental updates should their user navigate back to some particular UI that would benefit from displaying the results of incremental delivery.
- Clients can always request incremental updates and know that they can defer those incremental updates once they are able to identify that the response will not be rendered onscreen.

Anecdotally, we do know that offering the ability to adjust how the on-client-device data delivery behaves can significantly impact throughput itself and also power cost (mostly due to changes in batching during delivery).

Thanks,
Eric

> On Jun 4, 2020, at 4:33 PM, Lucas Pardue <[email-masked]> wrote:
> 
> Hello folks,
> 
> The Extensible Priorities draft has an open issue on the topic of reprioritization [1] and the May 2020 HTTP Interim session [2] pivoted towards it. The discussion highlighted that reprioritization is something we need to get to the bottom of in order to unblock progressing this draft.
> 
> Our definition of the reprioritization feature is purposefully narrow, but the frame-related mechanics cause complications for implementations. One option on the table is to take reprioritization out of the critical path of draft-ietf-httpbis-priority by extracting the text to leave a simpler definition of just the scheme and the Priority header signal. The extracted text could be put in a separate I-D, reworked, replaced, or dropped altogether. The choice of action is ultimately up to the WG, so that is why we’re sending this email. 
> 
> Removing reprioritization from draft-ietf-httpbis-priority sounds pretty drastic but in all the work that’s got us here, we’ve struggled to find data that backs up its efficacy.
> 
> Reducing Extensible Priorities to its core, clients issue priority signals (U and I) based on the expectation that the server, if possible, will transmit responses in the order of their urgency and request order (inferred by stream ID). Reprioritization is a client sending a subsequent signal (U’ and I’) that modifies the priority of in-flight responses. Reprioritization is not:
> 
> Sending a batch of requests and signalling the desire for later requests to be sent before earlier ones. By design, that is supported using urgency.
> Purposeful ordering of requests to meet a priority objective. This a client implementation choice.
> Aborting requests or responses that are in flight. By design, that is a function provided by HTTP/2 or QUIC streams that is actioned by implementation choice. 
> Manipulating a dependency tree through the lifetime of a connection. By design, that is not required.
> Any other mechanisms to adjust the server’s scheduling of response data. That is out of scope.
> 
> We’d be very interested to hear from people who support keeping reprioritization and can provide data, directly or indirectly, that the way it is applied in the extensible priority scheme provides tangible benefits. Data to the opposite effect is also of interest.
> 
> Cheers
> Kazuho and Lucas
> [1] - https://github.com/httpwg/http-extensions/issues/1021 <https://github.com/httpwg/http-extensions/issues/1021>
> [2] - https://github.com/httpwg/wg-materials/blob/gh-pages/interim-20-05/minutes.md#priorities <https://github.com/httpwg/wg-materials/blob/gh-pages/interim-20-05/minutes.md#priorities>

---

From: Kazuho Oku <[email-masked]>
Date: Tue, 9 Jun 2020 13:04:02 +0900

Hello all,

Thank you for all the discussion.

To me it seems that there's sentiment that reprioritization would be
useful, even if it is hard to immediately prove that it is. I share that
sentiment.

At the same time, as others (mostly recently Lucas in this thread) have
pointed out, reprioritization is more complex to implement than compared to
just having initial priorities. That is because the servers need to take
care of frames arriving out-of-order across multiple streams.

That brings my mind back to the question that Lucas posted: even if we
think that reprioritization would be useful, should that be an
indispensable part of Extensible Priorities?

We know that the prioritization signals sent by clients are merely advices;
servers might or might not honor them. What we've learned from HTTP/2 is
that we cannot assume that the servers do the "correct" thing, if the
scheme being defined is complex.

Based on these points, my preference is starting to lean towards *not*
having reprioritization as an indispensable feature of Extensible
Priorities.

I am totally fine (and supportive) of having reprioritization as an
optional feature. I do not have a strong opinion regarding if it should be
kept as an optional feature of the current draft, or if it should be a
different draft.

What do you think? Would the user experience deteriorate if the server only
supports initial priorities? Would that deterioration be significant to the
extent that it would be a blocker for us to proceed?

2020年6月9日(火) 9:46 Eric Kinnear <[email-masked]>:

> Hi all,
>
> As another datapoint, Safari (and URLSession for general HTTP use outside
> the browser) use reprioritization to update the incremental flag.
>
> One place where we do that update is during a download in Safari: since
> some responses are displayed and some responses are downloaded, we don’t
> know upfront if we’re going to be rendering the content onscreen or putting
> it in the downloads list. More generally, we support the concept of “fetch
> the response for this request” as well “download this resource to some path
> on disk for me to deal with later”, and switching between them causes us to
> signal whether we are [no longer] interested in incremental delivery of the
> resource.
>
> Unfortunately, we don’t currently have any numbers to share about efficacy
> here, but it does seem as though the ability to update the value that we
> sent is key in supporting an API that allows both directions of update:
> - Clients can defer updates to a resource, knowing that they can
> “re-request” such incremental updates should their user navigate back to
> some particular UI that would benefit from displaying the results of
> incremental delivery.
> - Clients can always request incremental updates and know that they can
> defer those incremental updates once they are able to identify that the
> response will not be rendered onscreen.
>
> Anecdotally, we do know that offering the ability to adjust how the
> on-client-device data delivery behaves can significantly impact throughput
> itself and also power cost (mostly due to changes in batching during
> delivery).
>
> Thanks,
> Eric
>
>
>    - Sending a batch of requests and signalling the desire for later
>    - Purposeful ordering of requests to meet a priority objective. This a
>    - Aborting requests or responses that are in flight. By design, that
>    is a function provided by HTTP/2 or QUIC streams that is actioned by
>    implementation choice.
>    - Manipulating a dependency tree through the lifetime of a connection.
>    - Any other mechanisms to adjust the server’s scheduling of response

-- 
Kazuho Oku

---

From: "Martin Thomson" <[email-masked]>
Date: Tue, 09 Jun 2020 14:29:24 +1000

> having reprioritization as an indispensable feature of Extensible 

This seems sensible.

The "extensible" part is helpful here.  While we might not need to relying on the priorities part being extensible, we know that the protocol is.  We don't really lose anything by decoupling this part of the spec, but we might gain some certainty.

---

From: Bence Béky <[email-masked]>
Date: Tue, 9 Jun 2020 08:11:43 -0400

Hi all,

I find the statement that the client often learns information that
influences priority after the request is sent conceivable.  To me this
implies that the additional benefit of reprioritization is comparable to
the benefit of prioritization in the first place.  Unfortunately, however,
I do not have any data on the effect of reprioritization on the users' page
load experience, neither for HTTP/2 or HTTP/3.

However, I can speak to the complexity part.  I have implemented the
PRIORITY_UPDATE frame for HTTP/3 both in the client and in the server
network stack.  I consider the complexity of server-side buffering and
resource usage limiting minimal.  Because of this, I oppose removing
reprioritization from the Extensible Prioritization Scheme for HTTP draft.

Since Chrome renderer has already been sending reprioritization signals to
the network stack when an image goes in or out of the current view, now
PRIORITY_UPDATE frames should be sent upon these events when using HTTP/3.
Since we had reprioritization in place in the renderer for the HTTP/2 case,
this essentially came for free for HTTP/3 with the network stack change.

Cheers,

Bence

On Tue, Jun 9, 2020 at 12:08 AM Kazuho Oku <[email-masked]> wrote:

> We know that the prioritization signals sent by clients are merely
> advices; servers might or might not honor them. What we've learned from
> HTTP/2 is that we cannot assume that the servers do the "correct" thing, if
> the scheme being defined is complex.
>
> What do you think? Would the user experience deteriorate if the server
> only supports initial priorities? Would that deterioration be significant
> to the extent that it would be a blocker for us to proceed?
>
>
>> Unfortunately, we don’t currently have any numbers to share about
>> efficacy here, but it does seem as though the ability to update the value
>> that we sent is key in supporting an API that allows both directions of
>> update:
>> Our definition of the reprioritization feature is purposefully narrow,
>> but the frame-related mechanics cause complications for implementations.
>> One option on the table is to take reprioritization out of the critical
>> path of draft-ietf-httpbis-priority by extracting the text to leave a
>> simpler definition of just the scheme and the Priority header signal. The
>> extracted text could be put in a separate I-D, reworked, replaced, or
>> dropped altogether. The choice of action is ultimately up to the WG, so
>> that is why we’re sending this email.
>>
>> Reducing Extensible Priorities to its core, clients issue priority
>> signals (U and I) based on the expectation that the server, if possible,
>> will transmit responses in the order of their urgency and request order
>>    - Purposeful ordering of requests to meet a priority objective. This
>>    a client implementation choice.
>>    - Manipulating a dependency tree through the lifetime of a
>>    connection. By design, that is not required.

---

From: Lucas Pardue <[email-masked]>
Date: Tue, 9 Jun 2020 15:15:44 +0100

Spinning off a thread of discussion focused toward implementation
complexity.

Thanks, for sharing your implementation insight Bence.

> reprioritization from the Extensible Prioritization Scheme for HTTP draft.

Speaking as an individual:

HTTP/3 offers a pretty rational base profile of functionality,it provides
multiplexed request/response without HoL blocking. Much of the
implementation complexity needed for this is now handled by the QUIC layer.

QUIC handles a lot of complex bits now. The remaining mandatory complexity
in HTTP/3 comes from QPACK static table and huffman coding. Victor recently
asked the QUIC WG about the possibility of further simplifying things by
allowing these opt-in [1]. Negotiating these features has some gnarly race
conditions that could be hard to fix with the protocol toolkit we have
today. Group consensus was that the design strikes a fair balance between
broad optimization and complexity; future work might let us fix the
gnarlies, so the issue was punted to a future version.

Endpoints can opt-in to two additional, more-specialized, performance
optimization features, at the cost of additional complexity: QPACK dynamic
compression and server push. The spec spells out some of the constraints
and trade offs an implementation needs to think about but the instantiation
of these features is specific to an endpoint applying some decisions to the
connection properties. Importantly, these two features can interact with
the progressively-stateful QPACK compression context and getting that wrong
(desync) can lead to security problems. So it is important to know that the
receiving peer is happy to receive QPACK or server push signals before you
send them. The spec spends quite a few words to describe these features,
even though endpoints are under no obligation to implement them or use them
on any connection where they are enabled.

I can hypothesize that an implementation with QPACK dynamic support has
already crossed the threshold of complexity that means implementing
reprioritization is not burdensome. I'd like to hear from other
implementers if they agree or disagree with this.

I tend to think of reprioritization as a more-specialized optimization of
priorities. In this sense, it is similar to QPACK and server push. The
important difference though is that extensible priorities purposefully
minimizes the need for progressive state. Ignoring a priority signal is
going to be safe. It may have a non-neglibile effect on performance, but it
is time bound and recoverable within a connection. In contrast, desync of
the old tree-based priorities could lead to strange state with no way to
recover, which means there was a stronger mandate to either a) process
PRIORITY frames even if the endpoint just wanted to implement something
minimally complex, or b) just ignore most things to be safe.

For the above reasons, IMO extensible priorities on the whole is pretty
lightweight and dispensable. I think there is a valid argument to document
reprioritization alongside the core scheme, this is in-keeping with QPACK
and server push.

Cheers,
Lucas

[1] - https://github.com/quicwg/base-drafts/issues/3622

---

From: Dmitri Tikhonov <[email-masked]>
Date: Tue, 9 Jun 2020 10:44:29 -0400

> implementers if they agree or disagree with this.

I don't think we can judge either way.  If Alice implements QPACK and
Bob implement reprioritization, results will vary based on their level
of competence.  The degree of burden will also vary for each
particular implementation.  Speaking for lsquic, reprioritization
had to [1] touch more code and was much more tightly coupled than
QPACK; on the other had, QPACK encoder logic was a lot more code.

At a higher level, I don't understand the concern with complexity.
If you look up "complexity" in the dictionary, you will see

    complexity (n), see QUIC.

  - Dmitri.

1. Before it was ripped out of the spec, that is, thanks a lot...

---

From: Patrick Meenan <[email-masked]>
Date: Tue, 9 Jun 2020 11:20:10 -0400

Maybe I'm missing something but the priority updates don't need to
coordinate across multiple data streams, just between the one stream that
is being reprioritized and the control stream.

Would something like this not work?
- Control stream gets priority update for stream X
- If stream X is known and the request side is complete/closed then update
the priority as requested
- If stream X is either not known or still in the process of receiving
request details, store the priority update for stream X in a fixed
queue/map (size can be small but a safe size would be the max number of
streams supported)
- If there is already a pending priority update for stream X, discard it
and replace it with the current priority update
- If the pending priority update queue is full, drop the oldest and insert
the new update
- When a new request stream closes, check the pending priority update queue
to see if there is an update waiting for the stream. If so, remove it from
the queue and apply the new priority

There should be no DOS concerns since the queue is fixed and small. The
performance overhead would be trivial if we assume that out-of-order
reprioritizations are rare (i.e. the list will almost always be empty).

---

From: Patrick Meenan <[email-masked]>
Date: Tue, 9 Jun 2020 11:26:51 -0400

Eric's download example is a great one for exposing the risks that would
come for an implementation that supported prioritization but not
reprioritization.

Take the trivial example of an anchor link that links to a download (say, a
200MB installer of some kind):
- When the user clicks on the link, the browser assumes it is doing a
navigation and issues the request with the "HTML" priority (relatively
high, possibly non-incremental
- When the response starts coming back, it has the content-disposition to
download to a file.
- At this point, the 200MB download will block every other lower-priority
request on the same connection (or possibly navigation if it is
non-incremental)
- The user clicks on another page on the same site and gets nothing or a
broken experience until the 200MB download completes

Without reprioritization the browser will effectively have to burn the
existing QUIC connection and issue any requests on a new connection (and
repeat for each new download).

Implementing prioritization without reprioritization in this case is worse
than having no prioritization support at all.

On Tue, Jun 9, 2020 at 8:16 AM Bence Béky <[email-masked]> wrote:

>>> As another datapoint, Safari (and URLSession for general HTTP use
>>> outside the browser) use reprioritization to update the incremental flag.
>>>

---

From: Lucas Pardue <[email-masked]>
Date: Tue, 9 Jun 2020 17:17:59 +0100

On Tue, Jun 9, 2020 at 4:27 PM Patrick Meenan <[email-masked]> wrote:

> Take the trivial example of an anchor link that links to a download (say,
> a 200MB installer of some kind):

Thanks Eric for presenting this case, and Patrick for breaking it down.
That does seem like a pretty bad outcome.

Is this a good candidate for a test case? IIUC correctly the problem might
occur today with HTTP/2 depending on how exclusive priorities are used. I'm
curious if browsers can share any more information about what they do
already. How does Firefox manage such a resource with it's priority groups?

Cheers
Lucas

---

From: Lucas Pardue <[email-masked]>
Date: Tue, 9 Jun 2020 20:22:10 +0100

Hey Dmitri,

On Tue, Jun 9, 2020 at 3:44 PM Dmitri Tikhonov <[email-masked]>
wrote:

> particular implementation.

I agree that, all things considered, QPACK and prioritization are
dissimilar. However, this thread is specifically exploring the mechanics of
the reprioritization mechanism, which requires a signal received on one
stream (the control stream) to affect the send behaviour on another. There
is always a possibility of a race here. My conjecture is that the
priorities race ends up being is similar to QPACK'S (i.e. handling blocked
streams). And therefore if Alice implements QPACK dynamic support
competently, then implementing reprioritization is no more difficult.

>   Speaking for lsquic, reprioritization

Thanks for sharing your experiences. If we take the scheduling aspects out
of consideration, the old HTTP/3 priority tree (+ placeholders etc) scheme
signals were pretty tough to implement. I suspect that extensible
priorities' reprioritization would be relatively more simple. But it would
be interesting to hear from someone that implemented the old scheme
compared with the new one.

Cheers
Lucas

---

From: Dmitri Tikhonov <[email-masked]>
Date: Tue, 9 Jun 2020 15:41:46 -0400

> competently, then implementing reprioritization is no more difficult.

My point was that Alice may have no problem implementing repriotization,
but Bob very well might!  That is to say, there may be more than one
person working on an HTTP/3 stack.  After Bob gives up after three
months leaving reprioritization a steaming pile of crap, Alice (who's
grown to hate that fool) inherits Bob's code, but may not be able to
make a good implementation given tight deadlines.  Alice gets blamed;
Bob gets promoted.  The story gets sadder and sadder in my mind, so
I better stop.

> signals were pretty tough to implement.

They were... that made it difficult to part with my implementation

> I suspect that extensible

I think so as well.  I will resurrect this thread once we have
reprioritization working and share my thoughts.

  - Dmitri.

---

From: "Roy T. Fielding" <[email-masked]>
Date: Tue, 9 Jun 2020 15:41:23 -0700

> Bob gets promoted.  The story gets sadder and sadder in my mind, so

Umm, yeah.

May I suggest that we include all of the signals necessary to reprioritize and
leave it up to the recipients whether or not to implement them? That's what
we have to deal with anyway given the latency issues.

....Roy

---

From: Kinuko Yasuda <[email-masked]>
Date: Thu, 11 Jun 2020 06:12:47 +0900

Hi all,

Reg: reprioritization benefit I can share some recent data for Chrome.  For
the two cases that are currently discussed I'm actually not fully sure
about its benefit.

For the renderer-triggered image reprioritization cases: this is a bit
interesting one, we recently found two things:
- Delaying to start low-prio requests could often work better (partly
because of server-side handling) than re-prioritizing while inflight
- In-lab measurements (tested with top 10k real sites, both on Mobile and
Desktop) showed that removing in-flight re-prioritization doesn't impact
page load performance a lot

I suspect this is maybe because server-side handling is not always perfect
and most of requests on the web are short-lived, and this may not be true
for the cases where long-running requests matter.  I don't have data for
whether may impact background / foreground cases (e.g. Chrome tries to
lower priorities when tabs become background)

For download cases, Chrome always starts a new download with a low priority
(even if it has started as a navigation), so reprioritization doesn't
happen.

Kinuko

On Wed, Jun 10, 2020 at 1:21 AM Lucas Pardue <[email-masked]>
wrote:

>> Implementing prioritization without reprioritization in this case is
>> worse than having no prioritization support at all.
>>
>

---

From: Kinuko Yasuda <[email-masked]>
Date: Thu, 11 Jun 2020 06:45:51 +0900

(Sorry, sent it too soon...)

On Thu, Jun 11, 2020 at 6:12 AM Kinuko Yasuda <[email-masked]> wrote:

> Hi all,
>
> Reg: reprioritization benefit I can share some recent data for Chrome.
> For the two cases that are currently discussed I'm actually not fully sure
> about its benefit.
>

Let me stress though that testing this with servers that can properly
handle reprioritization could change the landscape, and again this isn't
really capturing how it affects long-lived request cases, or cases where
tabs go foreground & background while loading, so for now I'm not very
motivated to remove the reprioritization feature either.

> For download cases, Chrome always starts a new download with a low
> priority (even if it has started as a navigation), so reprioritization
> doesn't happen.
>
> Kinuko
>
>
>
>
>
>
>>> Take the trivial example of an anchor link that links to a download
>>> (say, a 200MB installer of some kind):
>>> - When the response starts coming back, it has the content-disposition
>>> to download to a file.
>>> - At this point, the 200MB download will block every other
>>> lower-priority request on the same connection (or possibly navigation if it
>>> is non-incremental)
>> Is this a good candidate for a test case? IIUC correctly the problem
>> might occur today with HTTP/2 depending on how exclusive priorities are
>> used. I'm curious if browsers can share any more information about what
>> they do already. How does Firefox manage such a resource with it's priority
>> groups?
>>
>> Cheers
>> Lucas
>>
>>

---

From: Kazuho Oku <[email-masked]>
Date: Thu, 11 Jun 2020 08:53:47 +0900

> the priority as requested

The problem is that when a H3 server receives a reprioritization frame and
fails to find the state of the stream being designated by that frame, it
has to decide either to queue or drop the frame. As you correctly point
out, the size of the queue has to be bounded.

To determine if it should queue or drop, a server needs to have access to
both of the following states maintained by the QUIC stack:
* i) current maximum stream ID permitted to the peer
* ii) list of stream IDs that have not been closed yet

Without having access to (i), a server cannot reject reprioritization
frames specifying an unreasonable large stream ID. Without having access to
(ii), a server might start remembering information for streams that have
already been closed.

The question is if we think it is okay to require all QUIC stacks to
provide access to this information (or to provide an API that allows an
application to query if a given stream ID meets the two criteria).

I would also point out that the size of the queue should not be restricted
any further. This is because when reprioritization is considered as an
indispensable part of Extensible Priorities, a client might use the
reprioritization frame for sending initial priorities too, instead of using
the header field for indicating the initial priority.

That is what Chrome does today. If an HTML contains 100 images, and if
Chrome receives them at once, it sends 100 PRIORITY_UPDATE frames, then
sends the requests for all those images, assuming that 100 is the maximum
stream concurrency permitted by the server.

If some servers fail to implement reprioritization correctly, and if
clients rely overly on reprioritization, the negative impact on performance
could be far greater than when *not* having reprioritization. I think that
the concern that some of us have, and the reason why they (I) think
defining reprioritization as an optional feature would be a safer approach.

> - When a new request stream closes, check the pending priority update
> queue to see if there is an update waiting for the stream. If so, remove it
> from the queue and apply the new priority
>
> On Tue, Jun 9, 2020 at 10:48 AM Dmitri Tikhonov <
> [email-masked]> wrote:
>

-- 
Kazuho Oku

---

From: Yoav Weiss <[email-masked]>
Date: Thu, 11 Jun 2020 09:51:39 +0200

On Thu, Jun 11, 2020 at 1:57 AM Kazuho Oku <[email-masked]> wrote:

>> - If stream X is known and the request side is complete/closed then
>> update the priority as requested
>>
>

If what Chrome is doing today is sub-optimal, it would be great if you
could file an issue on that front.

> defining reprioritization as an optional feature would be a safer approach.

If that's indeed the case, we shouldn't define reprioritization *at all*.
Making it optional is a cop-out, which would result in inconsistencies,
meaning clients can't rely on it and need to work-around its absence.
We should decide if reprioritization is good or bad, based on as much data
as we can pull, and make sure it's implemented only if we see benefits for
it in some cases, and then make sure it's only used in those cases.

>> - If the pending priority update queue is full, drop the oldest and
>> insert the new update

---

From: "Martin Thomson" <[email-masked]>
Date: Thu, 11 Jun 2020 17:59:03 +1000

On Thu, Jun 11, 2020, at 17:51, Yoav Weiss wrote:
> If that's indeed the case, we shouldn't define reprioritization *at 
> all*. Making it optional is a cop-out, which would result in 
> inconsistencies, meaning clients can't rely on it and need to 
> work-around its absence.

That is indeed what we are headed for.  But you can't levy a requirement on servers to implement something like this.  And even if they do, they won't all make the same decisions.

> We should decide if reprioritization is good or bad, based on as much 
> data as we can pull, and make sure it's implemented only if we see 
> benefits for it in some cases, and then make sure it's only used in 
> those cases.

I would like the first part.  For the implementation piece, that depends on the strength of the arguments behind the first bit more than it does on our actions here.

---

From: Kazuho Oku <[email-masked]>
Date: Thu, 11 Jun 2020 17:41:51 +0900

2020年6月11日(木) 16:51 Yoav Weiss <[email-masked]>:

>> The problem is that when a H3 server receives a reprioritization frame
>> and fails to find the state of the stream being designated by that frame,
>> it has to decide either to queue or drop the frame. As you correctly point
>> I would also point out that the size of the queue should not be
>> restricted any further. This is because when reprioritization is considered
>> as an indispensable part of Extensible Priorities, a client might use the

If it is an issue of Chrome depends on if we think that the specification
can require all servers to implement reprioritization correctly. That's why
this is an specifaction issue.

> meaning clients can't rely on it and need to work-around its absence.

That depends on how much clients would rely on reprioritization. Unlike H2
priorities, Extensible Priority does not have inter-stream dependencies.
Therefore, losing *some* prioritization signals is less of an issue
compared to H2 priorities.

Assuming that reprioritization is used mostly for refining the initial
priorities of a fraction of all the requests, I think there'd be benefit in
defining reprioritization as an optional feature. Though I can see some
might argue for not having reprioritization even as an optional feature
unless there is proof that it would be useful.

-- 
Kazuho Oku

---

From: Stefan Eissing <[email-masked]>
Date: Mon, 15 Jun 2020 09:55:36 +0200

> Am 11.06.2020 um 10:41 schrieb Kazuho Oku <[email-masked]>:
> 
> That depends on how much clients would rely on reprioritization. Unlike H2 priorities, Extensible Priority does not have inter-stream dependencies. Therefore, losing *some* prioritization signals is less of an issue compared to H2 priorities.
> 
> Assuming that reprioritization is used mostly for refining the initial priorities of a fraction of all the requests, I think there'd be benefit in defining reprioritization as an optional feature. Though I can see some might argue for not having reprioritization even as an optional feature unless there is proof that it would be useful.

> We should decide if reprioritization is good or bad, based on as much data as we can pull, and make sure it's implemented only if we see benefits for it in some cases, and then make sure it's only used in those cases.

When thinking about priority implementations, I recommend thinking about a H3 reverse proxy in front of a legacy H1 server. Assume limited memory, disk space and backend connections.

(Re-)prioritization in H2 works well for flow control, among the streams that have response data to send. Priorities can play a part in server scheduling, but
it's more tricky. By "scheduling" I mean that the server has to pick one among the opened streams for which it wants to compute a response for. This is often impossible to re-prioritize afterwards (e.g. suicidal for a server implementation).

If we would do H2 a second time, my idea would be to signal priorities in the HTTP request in a connection header and use this in the H2 frame layer to allocate DATA space on the downlink. Leave out changing priorities on a request already started. Let the client use its window sizes if it feels the need.

Cheers, Stefan (lurking)

---

From: Yoav Weiss <[email-masked]>
Date: Mon, 15 Jun 2020 10:28:37 +0200

On Mon, Jun 15, 2020 at 9:55 AM Stefan Eissing <[email-masked]>
wrote:

> > That depends on how much clients would rely on reprioritization. Unlike
> H2 priorities, Extensible Priority does not have inter-stream dependencies.
> data as we can pull, and make sure it's implemented only if we see benefits
> for it in some cases, and then make sure it's only used in those cases.
>
> When thinking about priority implementations, I recommend thinking about a
> H3 reverse proxy in front of a legacy H1 server. Assume limited memory,
> disk space and backend connections.
>
> (Re-)prioritization in H2 works well for flow control, among the streams
> that have response data to send. Priorities can play a part in server
> scheduling, but
> it's more tricky. By "scheduling" I mean that the server has to pick one
> among the opened streams for which it wants to compute a response for. This
> is often impossible to re-prioritize afterwards (e.g. suicidal for a server
> implementation).
>

Can you expand on why it is "suicidal"?

>
> If we would do H2 a second time, my idea would be to signal priorities in
> the HTTP request in a connection header and use this in the H2 frame layer
> to allocate DATA space on the downlink. Leave out changing priorities on a
> request already started. Let the client use its window sizes if it feels
> the need.
>
> Cheers, Stefan (lurking)

---

From: Stefan Eissing <[email-masked]>
Date: Mon, 15 Jun 2020 11:03:19 +0200

> Am 15.06.2020 um 10:28 schrieb Yoav Weiss <[email-masked]>:
> 
> 
> 
> On Mon, Jun 15, 2020 at 9:55 AM Stefan Eissing <[email-masked]> wrote:

It is tricky to obey re-prioritizations to the letter, managing memory+backend connections and protecting the infrastructure against DoS attacks. The reality is that there are limited resources and a server is expected to protect those. It's a (pun intended) top priority.

Another priority topping the streams is the concept of fairness between connections. In Apache httpd, the resources to process h2 streams are foremost shared evenly between connections. The share a connection gets is then allocated to streams based on current h2 priority settings. Any change after that will "only" affect the downstream DATA allocation. Also, the number of "active" streams on a connection is dynamic. It will start relatively small and grow if the connection is well behaving, shrink if it is not. That one of the reasons that Apache was only partially vulnerable to a single issue on the Netflix h2 cve list last year (the other being nghttp2).

tl;dr

By "suicidal" I mean a server failing the task of process thousands of connections in a consistent and fair manner.

---

From: Yoav Weiss <[email-masked]>
Date: Mon, 15 Jun 2020 12:14:53 +0200

On Mon, Jun 15, 2020 at 11:03 AM Stefan Eissing <
[email-masked]> wrote:

> > > That depends on how much clients would rely on reprioritization.
> Unlike H2 priorities, Extensible Priority does not have inter-stream
> dependencies. Therefore, losing *some* prioritization signals is less of an
> issue compared to H2 priorities.
> > >
> > When thinking about priority implementations, I recommend thinking about
> a H3 reverse proxy in front of a legacy H1 server. Assume limited memory,
> It is tricky to obey re-prioritizations to the letter, managing
> memory+backend connections and protecting the infrastructure against DoS
> attacks. The reality is that there are limited resources and a server is
> expected to protect those. It's a (pun intended) top priority.
>
> Another priority topping the streams is the concept of fairness between
> connections. In Apache httpd, the resources to process h2 streams are
> foremost shared evenly between connections.

That makes sense. Would re-prioritization of specific streams somehow
require to change that?

> The share a connection gets is then allocated to streams based on current
> h2 priority settings. Any change after that will "only" affect the
> downstream DATA allocation.

I *think* this makes sense as well, assuming that by "downstream" you mean
"future". Is that what you meant? Or am I missing something?

Also, the number of "active" streams on a connection is dynamic. It will
> start relatively small and grow if the connection is well behaving, shrink
> if it is not. That one of the reasons that Apache was only partially
> vulnerable to a single issue on the Netflix h2 cve list last year (the
> other being nghttp2).
>
> tl;dr
>
> By "suicidal" I mean a server failing the task of process thousands of
> connections in a consistent and fair manner.
>

Apologies if I'm being daft, but I still don't understand how (internal to
a connection) stream reprioritization impacts cross-connection fairness.

> >
> >
> > If we would do H2 a second time, my idea would be to signal priorities
> in the HTTP request in a connection header and use this in the H2 frame
> layer to allocate DATA space on the downlink. Leave out changing priorities
> on a request already started. Let the client use its window sizes if it
> feels the need.
> >
> > Cheers, Stefan (lurking)
>
>

---

From: Stefan Eissing <[email-masked]>
Date: Mon, 15 Jun 2020 13:17:55 +0200

Stefan Eissing

<green/>bytes GmbH
Hafenweg 16
48155 Münster
www.greenbytes.de

> Am 15.06.2020 um 12:14 schrieb Yoav Weiss <[email-masked]>:
> 
> 
> 
> On Mon, Jun 15, 2020 at 11:03 AM Stefan Eissing <[email-masked]> wrote:
> 
> Another priority topping the streams is the concept of fairness between connections. In Apache httpd, the resources to process h2 streams are foremost shared evenly between connections.
> 
> That makes sense. Would re-prioritization of specific streams somehow require to change that?
>  
> The share a connection gets is then allocated to streams based on current h2 priority settings. Any change after that will "only" affect the downstream DATA allocation.
> 
> I *think* this makes sense as well, assuming that by "downstream" you mean "future". Is that what you meant? Or am I missing something?
> 
> Also, the number of "active" streams on a connection is dynamic. It will start relatively small and grow if the connection is well behaving, shrink if it is not. That one of the reasons that Apache was only partially vulnerable to a single issue on the Netflix h2 cve list last year (the other being nghttp2).
> 
> tl;dr
> 
> Apologies if I'm being daft, but I still don't understand how (internal to a connection) stream reprioritization impacts cross-connection fairness.

*fails to imagine Yoav as being daft*

A server with active connections and workers. For simplicity, assume that each ongoing request allocates a worker.
- all workers are busy
- re-prio arrives and makes a stream A, being processed, depend on a stream B which has not been assigned a worker yet.
- ideally, the server would freeze the processing of A and assign the resources to B. 
- however re-allocating the resources is often not possible  (Imagine a CGI process running or a backend HTTP/1.1 or uWSGI connection.)
- the server can only suspend the worker or continue processing, ignoring the dependency.
- a suspended worker is very undesirable and a possible victim of a slow-loris attack
- To make this suspending less sever, the server would need to make processing of stream B very important. To unblock it quickly again. This is then where unfairness comes in.

The safe option therefore is to continue processing stream A and ignore the dependency on B. Thus, priorities are only relevant:
1. when the next stream to process on a connection is selected
2. when size/number of DATA frames to send is allocated on a connection between all streams that want to send

(Reality is often not quite as bad as I described: when static file/cache resources are served for example, a worker often just does the lookup, producing a file handle very quickly. A connection easily juggles a number of file handles to stream out according to priorities and stalling one file on another comes at basically no risk and cost.)

Now, this is for H2 priorities. I don't know enough about QUIC priorities to have an opinion on the proposals. Just wanted to point out that servers see the world a little different than clients. ;)

Cheers, Stefan

---

From: Yoav Weiss <[email-masked]>
Date: Mon, 15 Jun 2020 13:43:47 +0200

On Mon, Jun 15, 2020 at 1:18 PM Stefan Eissing <[email-masked]>
wrote:

> > > > Assuming that reprioritization is used mostly for refining the
> initial priorities of a fraction of all the requests, I think there'd be
> benefit in defining reprioritization as an optional feature. Though I can
> see some might argue for not having reprioritization even as an optional
> feature unless there is proof that it would be useful.
> > >
> > >
> > > > We should decide if reprioritization is good or bad, based on as
> much data as we can pull, and make sure it's implemented only if we see
> benefits for it in some cases, and then make sure it's only used in those
> cases.
> > >
> > > When thinking about priority implementations, I recommend thinking
> about a H3 reverse proxy in front of a legacy H1 server. Assume limited
> memory, disk space and backend connections.
> > >
> > > (Re-)prioritization in H2 works well for flow control, among the
> streams that have response data to send. Priorities can play a part in
> server scheduling, but
> > > it's more tricky. By "scheduling" I mean that the server has to pick
> one among the opened streams for which it wants to compute a response for.
> This is often impossible to re-prioritize afterwards (e.g. suicidal for a
> server implementation).
> > >
> > The share a connection gets is then allocated to streams based on
> current h2 priority settings. Any change after that will "only" affect the
> > I *think* this makes sense as well, assuming that by "downstream" you
> mean "future". Is that what you meant? Or am I missing something?
> >
> > Apologies if I'm being daft, but I still don't understand how (internal
> to a connection) stream reprioritization impacts cross-connection fairness.
>
:)

Thanks for outlining the server-side processing!

> - re-prio arrives and makes a stream A, being processed, depend on a
> stream B which has not been assigned a worker yet.
>

OK, I now understand that this can be concerning.
IIUC, this part is solved by with Extensible Priorities (because there's no
dependency tree).

Lucas, Kazuho - can you confirm?

> - however re-allocating the resources is often not possible  (Imagine a
> CGI process running or a backend HTTP/1.1 or uWSGI connection.)
> - To make this suspending less sever, the server would need to make
> processing of stream B very important. To unblock it quickly again. This is
> then where unfairness comes in.
>
> The safe option therefore is to continue processing stream A and ignore
> the dependency on B. Thus, priorities are only relevant:
> (Reality is often not quite as bad as I described: when static file/cache
> resources are served for example, a worker often just does the lookup,
> producing a file handle very quickly. A connection easily juggles a number
> of file handles to stream out according to priorities and stalling one file
> on another comes at basically no risk and cost.)
>
> Now, this is for H2 priorities. I don't know enough about QUIC priorities
> to have an opinion on the proposals. Just wanted to point out that servers
> see the world a little different than clients. ;)
>

I checked and it seems like Chromium does indeed change the parent
dependency as part of reprioritization. If the scenario you outlined is a
problem in practice, we should discuss ways to avoid doing that with H2
priorities.

---

From: Patrick Meenan <[email-masked]>
Date: Mon, 15 Jun 2020 08:10:13 -0400

Even without a priority tree it is likely that the H3 extensible priorities
structure would cause not-yet-started responses to need to be scheduled
ahead of in-flight responses. The urgency value is effectively a
parent/child relationship.

It's not as unbounded as H2 but if you churned through a bunch of
reprioritizations with stalled streams you could cause issues for a server
that didn't protect against it.

Limiting the reprioritizations to "what stream to pick next" would help but
wouldn't solve the long download problem.

On Mon, Jun 15, 2020 at 7:44 AM Yoav Weiss <[email-masked]> wrote:

>
>
> On Mon, Jun 15, 2020 at 1:18 PM Stefan Eissing <
>> <https://www.google.com/maps/search/Hafenweg+16+%0D%0A48155+M%C3%BCnster?entry=gmail&source=g>
>> 48155 Münster
>> <https://www.google.com/maps/search/Hafenweg+16+%0D%0A48155+M%C3%BCnster?entry=gmail&source=g>
>> www.greenbytes.de
>>
>> > Also, the number of "active" streams on a connection is dynamic. It
>> will start relatively small and grow if the connection is well behaving,
>> shrink if it is not. That one of the reasons that Apache was only partially
> IIUC, this part is solved by with Extensible Priorities (because there's
> no dependency tree).
>
>> > > If we would do H2 a second time, my idea would be to signal
>> priorities in the HTTP request in a connection header and use this in the
>> H2 frame layer to allocate DATA space on the downlink. Leave out changing
>> priorities on a request already started. Let the client use its window
>> sizes if it feels the need.
>> > >
>> > > Cheers, Stefan (lurking)
>> >
>>
>>

---

From: Yoav Weiss <[email-masked]>
Date: Mon, 15 Jun 2020 14:51:49 +0200

On Mon, Jun 15, 2020 at 2:10 PM Patrick Meenan <[email-masked]> wrote:

> Even without a priority tree it is likely that the H3 extensible
> priorities structure would cause not-yet-started responses to need to be
> scheduled ahead of in-flight responses. The urgency value is effectively a

I wouldn't consider the inflight response dependent on the
not-yet-started one here, because the not-yet-started one doesn't need a
specific response to hold for it, it just needs *any* response to finish
(and free up a worker thread in the architecture Stefan outlined) in order
to be sent (with its appropriate priority).
So, it might be somewhat delayed, but won't be held back forever if a
specific response is a long sending one. (assuming the number of worker
thread is not very small)

> Limiting the reprioritizations to "what stream to pick next" would help
> but wouldn't solve the long download problem.
>
>>> > Another priority topping the streams is the concept of fairness
>>> between connections. In Apache httpd, the resources to process h2 streams
>>> are foremost shared evenly between connections.
>>> >
>>> > Apologies if I'm being daft, but I still don't understand how
>>> (internal to a connection) stream reprioritization impacts cross-connection
>>> fairness.
>>>
>>> A server with active connections and workers. For simplicity, assume
>>> that each ongoing request allocates a worker.
>>> - all workers are busy
>>> (Reality is often not quite as bad as I described: when static
>>> file/cache resources are served for example, a worker often just does the
>>> lookup, producing a file handle very quickly. A connection easily juggles a
>>> number of file handles to stream out according to priorities and stalling
>>> one file on another comes at basically no risk and cost.)
>>>
>>> Now, this is for H2 priorities. I don't know enough about QUIC
>>> priorities to have an opinion on the proposals. Just wanted to point out
>>> that servers see the world a little different than clients. ;)
>>>
>>

---

From: Patrick Meenan <[email-masked]>
Date: Mon, 15 Jun 2020 10:15:50 -0400

Yep, totally solvable, just not "perfectly". Something like setting
maximums at global and "current urgency" level would probably work well
enough. i.e. 12 workers per connection max, 6 workers max for the current
highest-urgency level. The servers also have no idea how quickly the
back-ends will fulfill the requests and probably need to start workers for
lower priority streams if there are only a few high-priority streams in
flight to make sure they have data to fill the pipe.

A trivial implementation that spawned a new worker every time a higher
priority request came in would be DOSable with reprioritization if a client
kept issuing high-urgency requests and immediately de-prioritizing them.

It's probably also worthwhile for browsers and web devs to keep all of this
in mind when issuing the requests where the optimal behavior from the
server's perspective would be to receive the stream requests in the order
of priority. Even without reprioritization of existing streams, injecting
higher priority streams ahead of in-flight lower priority streams is going
to be worse for perf than if the streams were originally requested in the
optimal order (how much worse is going to depend on the server
implementation).  Since it's all discovered dynamically on the browser and
server side, the web devs play a pretty big role here as well (though
browsers might be able to help absorb some of it by pacing new stream
requests as the initial parse/loading is happening depending on what is
already in-flight).

On Mon, Jun 15, 2020 at 8:52 AM Yoav Weiss <[email-masked]> wrote:

>>>> > > it's more tricky. By "scheduling" I mean that the server has to
>>>> pick one among the opened streams for which it wants to compute a response
>>>> for. This is often impossible to re-prioritize afterwards (e.g. suicidal
>>>> for a server implementation).
>>>> > >
>>>> > By "suicidal" I mean a server failing the task of process thousands
>>>> of connections in a consistent and fair manner.
>>>> >

---

From: Kazuho Oku <[email-masked]>
Date: Tue, 16 Jun 2020 09:06:36 +0900

2020年6月16日(火) 0:36 Barry Pollard <[email-masked]>:

> Probably a stupid question, but should prioritisation (and in particular
> reprioritization) really affect server side processing (i.e. sending it
> downstream to a backend) or only in deciding what to send back? That is, is
> prioritisation primarily about using server side resources the most
> efficiently, or about using the client-side bandwidth the most efficiently?
> Ideally both of course, but with that comes added complexity, and to me
> client-side bandwidth limits is the main reason for prioritisation.
>

I think this is a very good way of phrasing the problem, and I think that
the answer is that it should not be written in the spec. It is up to the
internals of each server.

Let's use Stefan's example: a H3 reverse proxy sitting in front of a legacy
H1 server.

Assuming that the legacy H1 server cannot handle many connections at once
(i.e. prefork server), the H3 reverse proxy needs to limit the number of
connections that it opens concurrently to the H1 server. For example, the
H3 reverse proxy might support maximum stream concurrency of 256, but limit
the number of inflight requests forwarded to the backend server to 8 per
each H3 connection. If the number of inflight requests sent from the client
exceeds the latter limit (i.e. 8), they get queued, and get issued as the
inflight requests to the backend server are retired.

I'm not sure about other H2 / H3 servers, but H2O does provide this
capability of limiting the backend concurrency [1].

In such a deployment, I would argue that the H3 reverse proxy should
respect the priorities when choosing a request from the queue, regardless
of the prioritization signal being initial or reprioritization. Otherwise,
the H3 reverse proxy would end up providing responses to requests mostly in
the order of the requests being issued.

Looking at the issue from a theoretical point, the reason for having a
priority signal is to change the order in which the responses are provided.
It is beneficial to respect the signal at any point where we might see
contention, especially at points we'd have severe contention. While it is
true that the biggest bottleneck is the downstream bandwidth, there could
be other severe bottlenecks depending on each deployment.

[1]
https://h2o.examp1e.net/configure/http2_directives.html#http2-max-concurrent-requests-per-connection

> So could you simplify this and concentrate on the return queue only - at
> least for reprioritization? There's already discussions to
> drop reprioritization completely, so limiting it to this (I'm assuming
> simpler) scope would perhaps save us from going to that extreme position
> but also avoid making this overly complex.
>
> So in Stefan's example earlier (reprioritization making request A already
> in process, dependent on the later received request B not started yet) we
> basically continue to process request A (as it's already started), and if
> it's ready to go, and B is still not, then start sending A - the dependency
> is only uses when both requests are at same stage and we need to make a
> priority call between them. If that takes some time to send and B becomes
> available during that time, then now we have a queue of bytes to send and
> so a choice about what to send in next batch of bytes. Then we can using
> the prioritization hints to send B's bytes in preferences to A's.
>
> So I agree with Stefan's point that "it is tricky to obey
> re-prioritizations to the letter" (impossible for responses already sent)
> but do we need to? Are they not just hints and the end of the day? And he
> also says "any change after that will 'only' affect the downstream DATA
> allocation" but I'd argue that's the main point.
>
> Or it could be I'm massively oversimplifying this and/or completely
> misunderstanding the problem. First post to this group after lurking for a
> while so be nice to me :-)
>
> On Mon, 15 Jun 2020 at 15:19, Patrick Meenan <[email-masked]> wrote:
>
>> It's probably also worthwhile for browsers and web devs to keep all of
>> this in mind when issuing the requests where the optimal behavior from the
>>>>>> > > > Am 11.06.2020 um 10:41 schrieb Kazuho Oku <[email-masked]
>>>>>> >:
>>>>>> > > >
>>>>>> > > > That depends on how much clients would rely on
>>>>>> reprioritization. Unlike H2 priorities, Extensible Priority does not have
>>>>>> inter-stream dependencies. Therefore, losing *some* prioritization signals
>>>>>> is less of an issue compared to H2 priorities.
>>>>>> > > >
>>>>>> > > > We should decide if reprioritization is good or bad, based on
>>>>>> as much data as we can pull, and make sure it's implemented only if we see
>>>>>> > > When thinking about priority implementations, I recommend
>>>>>> thinking about a H3 reverse proxy in front of a legacy H1 server. Assume
>>>>>> limited memory, disk space and backend connections.
>>>>>> > >
>>>>>> > I *think* this makes sense as well, assuming that by "downstream"
>>>>>> you mean "future". Is that what you meant? Or am I missing something?
>>>>>> >
>>>>> IIUC, this part is solved by with Extensible Priorities (because
>>>>> there's no dependency tree).
>>>>>
>>>>>> - however re-allocating the resources is often not possible  (Imagine
>>>>>> a CGI process running or a backend HTTP/1.1 or uWSGI connection.)
>>>>>> The safe option therefore is to continue processing stream A and
>>>>>> ignore the dependency on B. Thus, priorities are only relevant:
>>>>>> 2. when size/number of DATA frames to send is allocated on a
>>>>>> connection between all streams that want to send
>>>>>>

-- 
Kazuho Oku

---

From: Yoav Weiss <[email-masked]>
Date: Tue, 16 Jun 2020 07:39:55 +0200

> optimal order (how much worse is going to depend on the server

I was going to ask exactly that :)
Seems like the problem of "all the workers are busy and now we need to
handle a high priority request" is not inherently different between the
reprioritization case and the case of a high priority request that just
arrived.

Since it's all discovered dynamically on the browser and server side, the
> web devs play a pretty big role here as well (though browsers might be able
> to help absorb some of it by pacing new stream requests as the initial
> parse/loading is happening depending on what is already in-flight).
>

Sure. This is something browsers can do to work around lack of proper
priority implementations in servers. But stalling requests also has its
tradeoffs. Would be good if the next iteration of priorities in the
protocol didn't require us to fall back to order-based hacks.

---

From: Barry Pollard <[email-masked]>
Date: Tue, 16 Jun 2020 07:40:45 +0100

> the order of the requests being issued.

That I agree with. But some prioritisation choices are discrete - for
backend requests the request is either queued or sent to back end or
completed by the backend. I wouldn’t try to interrupt that after it’s been
sent to the back end. So you use the best prioritisation signals available
at the time when choosing which request to the backend.

If 8 items come in at medium priority and they all require back end calls,
and we can only have 8 backend resources in flight at same time, then send
them. If a 9th high priority request then comes in while those 8 are being
processed then tough - there are no free slots to the backend for that
request despite it being high priority - those backend slots were filled
with the best prioritisation signals available at the time.

Of course if 10 items need backend resources, with differing priorities,
then use that priorities to decide which 8 of those to send first. But I’m
Just saying this is less likely to happen until all the back end slots are
filled because 10 things do not come in at once - they come in one by one
and I’d argue they should be sent to the back end ASAP and then left to
complete, rather than holding back requests or interrupting requests
already sent to back end. So initially, until all backend slots are filled,
prioritisation is not used here because effectively there is no queue
initially.

Either way, after the back end process is complete for one or more requests
and returned to the web server, we’ve another queue of bytes to return to
the browser and so another opportunity to use prioritisation to select
which stream’s bytes to send back.

Basically what I’m saying is only use prioritisation when there’s a queue
and a choice to be made.

However, as there is more likely to be queuing on the final return step to
the client, we’ll end up using prioritisation more there (which is no bad
thing!).

---

From: Barry Pollard <[email-masked]>
Date: Mon, 15 Jun 2020 16:36:33 +0100

On Mon, 15 Jun 2020 at 15:19, Patrick Meenan <[email-masked]> wrote:

>>>>> > > > That depends on how much clients would rely on reprioritization..

---

From: Kazuho Oku <[email-masked]>
Date: Wed, 17 Jun 2020 16:55:38 +0900

> motivated to remove the reprioritization feature either.

Hi Kinuko,

Thank you for sharing your data. I feel a bit sad that reprioritization
isn't showing much benefit at the moment. I tend to agree that we are
likely to see different results between server implementations and HTTP
versions being used. The effectiveness of reprioritization depends on the
depth of the send buffer (after prioritization decision is made), at least
to certain extent.

>
>
>> I suspect this is maybe because server-side handling is not always
>> perfect and most of requests on the web are short-lived, and this may not
>> be true for the cases where long-running requests matter.  I don't have
>> data for whether may impact background / foreground cases (e.g. Chrome
>> tries to lower priorities when tabs become background)
>>
>>>> Eric's download example is a great one for exposing the risks that
>>>> would come for an implementation that supported prioritization but not
>>>> reprioritization.
>>>>
>>>> - The user clicks on another page on the same site and gets nothing or
>>>> a broken experience until the 200MB download completes
>>>>

-- 
Kazuho Oku

---

From: Yoav Weiss <[email-masked]>
Date: Wed, 17 Jun 2020 11:43:25 +0200

On Wed, Jun 17, 2020 at 9:55 AM Kazuho Oku <[email-masked]> wrote:

>>> - In-lab measurements (tested with top 10k real sites, both on Mobile
>>> and Desktop) showed that removing in-flight re-prioritization doesn't
>>> impact page load performance a lot
>>>
>>

FWIW, I added a flag
<https://chromium-review.googlesource.com/c/chromium/src/+/2232923> to turn
off Chromium's H2 request prioritization. I believe +Pat Meenan
<[email-masked]> is currently running tests with and without this flag
a list of servers we estimate is likely to handle them well.

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 19 Jun 2020 17:22:30 +0100

Thanks for the different perspectives on this. Quoting isn't going to work
so great so I'll pick out some points from this and the parent thread:

Google have added a flag [1] to Chrome that allows toggling of H2
reprioritization, some experimental work is happening with this. Thanks!

We've talked a bit about how priorities might affect both scheduling server
work, and selecting the bytes to emit from the server's response send
queue. I agree with Kazuho that we don't want to specify much about the
internals of server applications. However, there are some DoS
considerations (depending on the outcome of the repriority discussion), so
looking ahead we might find it is useful to capture anything already not
already covered in the spec.

The server's role in optimizing the use of available bandwidth is an
interesting perspective to take, especially considering the client's
responsibility for providing flow control updates. In the basic HTTP/3
priority implementation of the quiche library, the application processes
the priority header and provides that information when sending response
data. Internally the library uses an implementation-specific API method to
set the priority of the transport stream; this does account for the
properties Kazuho mentioned i) it returns an error if the stream ID exceeds
current maximum ii) it no-ops if the stream ID refers to a closed stream.
HTTP response payload data is written to each stream until the QUIC layer
tells me it cannot take any more because the send window is full. In a
separate loop, the QUIC layer selects stream data to transmit based on the
priority. The client's expedience in providing flow control updates affects
phase 1 (local buffering) but not phase 2 (emission). A client
reprioritization would affect phase 2 not phase 1. In my case, quiche's
transport priority method does account for the properties Kazuho mentioned
i) it returns an error if the stream ID exceeds current maximum ii) it
no-ops if the stream ID refers to a closed stream.

The funnies will happen with trying to accommodate reprioritization
signals:

   - Exposing the reception of a reprioritization signal (PRIORITY_UPDATE
   frame) to the application might be useful, or useless if we consider some
   of Stefan's points.
   - Reordering can cause the reprioritization to arrive before the initial
   priority. Exposing an event to the application just made things harder.
      - Reordering isn't the only concern. In quiche, when an application
      asks us to read from transport, we internally always read from
the control
      stream and QPACK streams before request streams. So we'd always pull out
      the PRIORITY_UPDATE first.
      - Exposing this scenario of reprioritization event to the application
      is mostly useless because the application has no idea of what is being
      reprioritized. If the priority is used for deciding server work,
one of the
      layers above transport needs to first validate and then remember the
      details. This means that the library needs to expose a broader
API surface
      than it already does (e.g. exposing Kazuho's properties)
      - If the transport layer API simply actions the last invoked
   priority, naively calling it when the signals were received in the "wrong"
   order means that reprioritization might be ignored.
   - If a reprioritization event is simply hair pinned back into the quiche
   library, there is an argument for not exposing it.
   - I could simply accommodate things by modifying the transport priority
   method to take a bool, is_initial. This would prevent an initial priority
   from being applied after a reprioritization. In conjunction, defining in
   the spec that initial priority is *always the header* would remove some of
   the complexity of buffering data above the transport layer.

All of this is additional consideration and speculation specific to my
implementation, applicability to others can vary. I can see how things
would be harder for implementers that attempt to manage more of the
priority scheme in the HTTP/3 layer than the QUIC one.

We also haven't mentioned reprioritization of server push. The client
cannot control the initial priority of a pushed response and there is an
open issue about the default priority of a push [2]. In that thread we are
leaning towards defining no default priority and letting a server pick
based on information *it* has. However, Mike Bishop's point about
reprioritizing pushes is interesting [3]. To paraphrase, if you consider
the RTT of the connection, there are three conditions:

a) the push priority was low: so no data was sent by the time a
reprioritization was received at the server. It is possible to apply the
reprioritization but importantly, the push was pointless and we may as well
have waited for the client to make the request.
b) the push priority was high, response size "small": so all data was sent
by the time a reprioritization was received at the server. The
reprioritization was useless.
c) the push priority was high, response size "large": some data sent at
initial priority but at the time a reprioritization is received at the
server, the remaining data can be sent appropriately. However, anecdotally
we know that pushing large objects is not a good idea.

If we agree to those conditions, it makes for a poor argument to keep
reprioritization of server push. But maybe there is data that disagrees.

Cheers
Lucas

[1] - https://chromium-review.googlesource.com/c/chromium/src/+/2232923
[2] - https://github.com/httpwg/http-extensions/issues/1056
[3] -
https://github.com/httpwg/http-extensions/issues/1056#issuecomment-593496441

---

From: Tom Bergan <[email-masked]>
Date: Fri, 19 Jun 2020 11:10:35 -0700

On Fri, Jun 19, 2020 at 9:26 AM Lucas Pardue <[email-masked]>
wrote:

>    - Reordering can cause the reprioritization to arrive before the
>    initial priority. Exposing an event to the application just made things
>    harder.
>       asks us to read from transport, we internally always read from the control
>       - Exposing this scenario of reprioritization event to the
>       application is mostly useless because the application has no idea of what
>       is being reprioritized. If the priority is used for deciding server work,
>       one of the layers above transport needs to first validate and then remember
>       the details. This means that the library needs to expose a broader API
>       surface than it already does (e.g. exposing Kazuho's properties)
>    - If a reprioritization event is simply hair pinned back into the
>    quiche library, there is an argument for not exposing it.
>    - I could simply accommodate things by modifying the transport
>    priority method to take a bool, is_initial. This would prevent an initial
>    priority from being applied after a reprioritization. In conjunction,
>    defining in the spec that initial priority is *always the header* would
>    remove some of the complexity of buffering data above the transport layer.
>

I didn't follow those details. I think it would be helpful to summarize the
API you're referring to.

This might be naive: While there are potentially tricky implementation
issues, as discussed by Kazuho and Patrick earlier, and potentially tricky
scheduling decisions, as discussed by Stefan, I'm not seeing how those
translate into API problems. Generally speaking, at the HTTP application
level, a request doesn't really exist until the HEADERS arrive (example
<https://golang.org/pkg/net/http/#Handler>; all other HTTP libraries I'm
familiar with work in basically the same way). At that point, the request
has an initial priority, defined either by the HEADERS, or by the
PRIORITY_UPDATE, if one arrived before HEADERS and there's no Priority
field. Further PRIORITY_UPDATEs can be delivered with whatever event
mechanism is most convenient (callbacks, channels, etc).

> reprioritization of server push. But maybe there is data that disagrees.

FWIW, I have the opposite interpretation. We can't ignore case (a) by
simply saying that "the push was pointless and we may as well have waited
for the client". That assumes the server should have known the push would
be pointless, but in practice that conclusion depends on a number of
factors that can be difficult to predict (size of other responses,
congestion control state, network BDP). Sometimes push is useful, sometimes
it's not, and when it's not, we should gracefully fallback to behavior that
is equivalent to not using push at all. From that perspective, case (a) is
WAI.

This lack of a graceful fallback is a big reason why push can be such a
footgun. Frankly, if pushes cannot be reprioritized in this way, then IMO
push is essentially dead as a feature (and it's already on rocky ground, as
it's so hard to find cases where it works well in the first place).

---

From: Lucas Pardue <[email-masked]>
Date: Fri, 19 Jun 2020 22:44:05 +0100

On Fri, Jun 19, 2020 at 7:10 PM Tom Bergan <[email-masked]> wrote:

> I didn't follow those details. I think it would be helpful to summarize
> the API you're referring to.
>

The quiche HTTP/3 library layer provides a poll() method that an
application calls. This queries readable transport streams and tries to
read requests (a complete headers list). Today, communicating the initial
priority is easy, I just pass the Priority header that I received. The
application chooses the priority to send responses by providing a desired
priority in the send_request() method - there is no coupling between the
request and response priority.  send_request() more or less passes
everything through to the QUIC library which manages the packetization of
STREAM frames once data is queued up. Minimal state is required in the
HTTP/3 library layer, once a response is started the application just tries
to fill the transport stream send buffer (via the H3 layer) as quickly as
the client drains it. When the application is ready to complete the
response, it send the last piece of data with a FIN. The application can
then forget about it. At this stage only the transport maintains stream
state, because it is not complete until the client reads the remaining
data. If we deem reprioritization as useful, then it needs to be supported
through the full lifetime of the stream.

Adding PRIORITY_UPDATE requires some more work in my HTTP/3 library layer.
One question that comes to mind is if the application cares about the full
sequence of PRIORITY_UPDATES, or if it is fine to skip/collapse them.
Before the request has been poll()ed out it seems sensible to buffer
PRIORITY_UPDATE, and then only present the most recent one. To call this
the initial priority is a slight fib, "most recent priority at the time you
discovered the request existed" is more apt but this is splitting hairs.
The one concern I would have is where the priority header and most-recent
value disagree. By passing both priorities out to the application I'm
making it responsible for picking.

Witholding a reprioritization event until after the request has been
poll()ed helps a bit. But I think there is not a clean way to deal with
reprioritization events after the application is done with the stream; if
the application is nominally done with processing the request all it can do
is tell the transport to behave differently. What's the point in that?
Attempting to explain the oddities caused by QUIC's behavior is part of the
API problem IMO.

>> b) the push priority was high, response size "small": so all data was
>> sent by the time a reprioritization was received at the server. The

That's a fair opinion too. Have you any thoughts about server push
reprioritization being a motivating factor for maintaining the feature?

Unfortunately I don't have a server push API that I can use to speculate
about reprioritization, although I suspect that I'd have similar problems
determining when a pushed response was "done", with the added complication
that something would need to maintain state to map push IDs to stream IDs.

Cheers
Lucas

---

From: Tom Bergan <[email-masked]>
Date: Fri, 19 Jun 2020 15:51:08 -0700

> reprioritization being a motivating factor for maintaining the feature?

The way I think of it is that reprioritzation can turn bad pushes into
neutral pushes, but it can't turn bad or neutral pushes into good pushes. I
validated the bad -> neutral hypothesis in a contrived / toy HTTP/2 sandbox
a few years ago. What's missing is a really convincing case where push is a
win (many good pushes). Despite a lot of looking, the only real-world case
I've found is that paper from Akamai a few years back.

I think my last email was too strong w.r.t. your above question. I don't
think we should decide the push question now and I don't think
reprioritzation alone is a motivating factor to maintain push. All I meant
to say is: I believe that reprioritization is helpful for push, assuming we
keep both.

---

From: Lucas Pardue <[email-masked]>
Date: Sat, 20 Jun 2020 00:15:29 +0100

> to say is: I believe that reprioritization is helpful for push, assuming we

Apologies. I could have phrased my question more clearly, the original
intent was "Assume that server push is here to stay. There may be cases
where reprioritizing in-flight pushes is useful, so does that make the
reprioritization feature more attractive on the whole?".

Regardless I think your additional description still stands. A server could
unwittingly push something at a higher priority than the client wants,
affecting the priority of things it does want. Without reprioritization the
only recourse is to starve the pushed stream of flow control or to close
the stream. I just don't know how often that would occur in practice.

Cheers
Lucas

---

From: Patrick Meenan <[email-masked]>
Date: Sat, 20 Jun 2020 10:17:11 -0400

An early read on Yoav's Canary test is that most metrics are neutral but
Largest Contentful Paint degrades ~6.8% on average and 12% at the 95th
percentile without reprioritization and Speed Index degrades 2.6% on
average and 5.4% at the 95th percentile. This is not entirely unexpected
because the main use case for reprioritization in Chrome right now is
boosting the priority of visible images after layout is done.

We'll see if it holds after the full test is complete. The early read is
from 3,000 of the 25,000 URLs that we are testing (all https hosted on
Fastly for simplicity since we know it handles HTTP/2 reprioritization
correctly).  The tests are all run at "3G Fast" speeds with desktop pages
to maximize the liklihood that there will be time for reprioritization to
happen.  I'll provide the full raw data as well as summary results when the
test is complete (at least another week, maybe 2).

On Wed, Jun 17, 2020 at 5:43 AM Yoav Weiss <[email-masked]> wrote:

> <https://chromium-review.googlesource.com/c/chromium/src/+/2232923> to
> turn off Chromium's H2 request prioritization. I believe +Pat Meenan
> <[email-masked]> is currently running tests with and without this
> flag a list of servers we estimate is likely to handle them well.
>
>
>>
>>
>>>
>>>
>>>> On Wed, Jun 10, 2020 at 1:21 AM Lucas Pardue <
>>>> [email-masked]> wrote:
>>>>
>>>>>> - When the response starts coming back, it has the
>>>>>> content-disposition to download to a file.
>>>>>> - The user clicks on another page on the same site and gets nothing
>>>>>> or a broken experience until the 200MB download completes
>>>>>>
>>>>>> Without reprioritization the browser will effectively have to burn
>>>>>> the existing QUIC connection and issue any requests on a new connection
>>>>>> (and repeat for each new download).
>>>>>>
>>>>> Thanks Eric for presenting this case, and Patrick for breaking it
>>>>> down. That does seem like a pretty bad outcome.
>>>>>