On Thu, Oct 9, 2014 at 12:12 PM, Chad Austin <caus...@gmail.com> wrote:
> Hi Ilya, > > This thread has been a bit confusing, partially because I did not have a > deep understanding of HTTP 2's priority semantics and partially because I > feel your responses have been too short and vague to truly answer the use > case described at the top of the thread. For example, you said "0-7 > priority is not sufficient. Please see the previous proposal.", yet I > don't see any discussion in the previous proposal about why 0-7 is not > sufficient. > > In addition, because I'm not sure it's clear, priorities and weights are > *different > concepts*. Weights are used to allocate resources between streams of > identical priority. Priorities are used to specify that one request should > be completed before another if possible. > That was never the case in SPDY. In v1-v3.1 priority never guaranteed strict delivery. Priorities were always advisory for the server, and in v4 draft we changed that to the tree model that is in HTTP/2. Also, note that this behavior is *intentional*. When using transport priorities, you're effectively telling the server: - I need all of these requests, please mux all the frames such that I receive all of the data as quickly as possible - Also, if possible, please allocate the pipe based on specified weights/dependencies/etc The above does not guarantee any order. Take an extreme example: B depends on A; A is taking 3 seconds to generate on the backend, while B is ready to ship. The server should not starve the connection while its waiting on A, and it should pump bytes for B until its ready to return bytes for A. If you need *strict* response ordering, then you have to choices: - Dispatch requests from the client based on completion of previous request, instead of firing them off simultaneously - Change your server to enforce your own arbitrary semantics (general purpose servers won't do this) > Per HTTP 2, "Streams with the same parent SHOULD be allocated resources > proportionally based on their weight." This is not the same thing as > priority. Weights may have value to others, but they don't have value to > the use case below. > Yes, which is why HTTP/2 introduces dependencies and weights. *The Use Case* > > Our application issues thousands (sometimes tens of thousands) of XHR HTTP > requests to populate a WebGL-rendered 3D scene. > > Many of those requests are higher *priority* than others, in that, if > possible, they should be completed *before* expending bandwidth on > lower-priority resources. Moreover, there is no benefit to having multiple > responses downloading simultaneously: assuming saturated bandwidth, it is > always better here to complete one response before moving to the next. > (Having two half-downloaded textures or meshes is not useful. Having one > fully-downloaded texture or mesh and one not started yet is useful.) > Makes sense. To match this, create a tree that captures these relationship. > From a software development point of view, the ideal JavaScript API would > allow issuing *all* requests simultaneously, indicating their relative > priority to the browser, and let the browser map the desired priority to > the underlying protocol stack. > Dependencies and weights. You're using priority values as crude levels to indicate "ordering". Instead, identify think of each "priority level" as a level in the deps tree, where each level can have multiple requests, resources for which can be further customized via weights. > > *Current Browser Behavior* > Browsers have widespread support for two protocols (HTTP and SPDY) and are > likely to support HTTP 2 very soon. > They will support HTTP/2, it's only a question of how soon. Latest FF and Chrome are already rolling out HTTP/2 support in stable channels, and the plan (for all browsers) is to actively deprecate SPDY. > *So what interface should the browser expose?* > > Before designing a browser API, a few questions must be answered: > > 1) Should the priority API support legacy HTTP and SPDY? > - SPDY is going to be aggressively deprecated. - Legacy HTTP has a lot of potential gotchas, I'd flag this as at risk. > 2) Should the priority API support future protocols beyond HTTP 2? > - Yes, it shouldn't be tied directly to HTTP/2 semantics. > 3) How likely is it future protocols will support non-dependency-based > priority models. > - Note that you *can* implement whatever you want on the server. Client sends its preferences, you do what you want. > 3) How much work should be placed on application developers? aka how > closely should the API fit the application domain? > - I'm not sure what "application domain" means, since that'll be different for every application. That said, yes, a sensible abstraction over the low-level plumbing is good. > IMO, the answers to the above questions are "yes", "yes", and "possible", > and "better for the API to fit the application domain than for the API to > reflect one possible underlying protocol so that a truer implementation in > non-HTTP-2 protocols is possible". > > In that light, I think your proposal [ > http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Aug/0081.html > ] is not satisfactory. It requires application bookkeeping to map priority > values to the linked list of XHRs, which: > > * in the case of SPDY, the browser must then convert back to 3-bit > integers somehow > Not an issue we should worry about. > * in the case of vanilla HTTP, the browser must convert the dependency > tree back to 32-bit integers. (or reimplement the browser's own priority > queue as a stream dependency model. I'd love to get a sense from browser > authors if that's likely to happen.) > I think it's premature to block on this. And yes, I'm also wondering if we should bother at all with 'plain HTTP'. > *Why not expose priority as a signed 32-bit integer?* > > For HTTP, this API is trivial to implement: just plumb the priority value > from Fetch down to the HTTP network stack. > > For SPDY, 32 bits would need to be mapped to 3 bits. Something like > Mozilla's algorithm is likely sufficient: > http://mxr.mozilla.org/mozilla-central/source/netwerk/protocol/http/SpdyStream3.cpp#370 > > For HTTP 2, mapping a 32-bit priority to an HTTP 2 linked list or skip > list is straightforward and O(lg N): > https://github.com/chadaustin/Web-Benchmarks/blob/master/http2/simpriority.py#L76 > I disagree, as that runs precisely counter to our experience with SPDY. You've cited Will's post that provides at least one concrete example where this fails, and there are more: https://insouciant.org/tech/spdy-prioritization-case-study-gmail/ > The final piece necessary is some calibration against the browser's own > prioritization. That is, the browser already prioritizes certain resources > - what priority value should they be given? Or, if you wanted an XHR to > have lower-priority than a certain script tag, you could say something like: > > var xhr = new XMLHttpRequest; > // assume large values are higher priority > xhr.fetch.priority = document.getElementById('script').fetch.priority - 1; > In terms of high level requirements: - The developer *must* be able to override browser set priorities. - Developer set priorities must be on same playing field as browser set priorities As far as the API... I don't think `priority` is sufficient, for reasons stated above. --- This is all great feedback and discussion -- thanks! Let's continue iterating... ig > On Wed, Oct 1, 2014 at 9:33 PM, Ilya Grigorik <igrigo...@gmail.com> wrote: > >> >> >> On Wed, Oct 1, 2014 at 8:39 PM, Chad Austin <caus...@gmail.com> wrote: >> >>> Weight is actually not what I want. I want priority. They're different >>> concepts in that priority implies trumping and weight implies proportional >>> resource allocation. >>> >>> That is, if I make 10 high-priority requests, 20 medium-priority >>> requests, and 30 low-priority requests, I don't want ANY of the >>> low-priority requests to consume any resources until either 1) all >>> higher-priority requests have been serviced or 2) there are spare resources >>> that cannot otherwise be used for higher-priority requests. >>> >> >> And.. you've just defined a three-level deep dependency tree, with >> weights for resources within each group. >> > > >> As you quoted, "Streams with the same parent SHOULD be allocated >>> resources proportionally based on their weight." Proportional allocation >>> would be incorrect for this use case. >>> >> >> Proportional within the same level of the tree, and based on assigned >> weights within that level. >> >> ig >> >> >> >>> >>> On Wed, Oct 1, 2014 at 8:19 PM, Ilya Grigorik <igrigo...@gmail.com> >>> wrote: >>> >>>> >>>> On Wed, Oct 1, 2014 at 7:59 PM, Chad Austin <caus...@gmail.com> wrote: >>>> >>>>> I don't see a way to set a priority value in there. The specific >>>>> wording is "Streams can be prioritized by marking them as dependent on >>>>> the, >>>>> completion of other streams". >>>>> >>>>> I see that a client can specify the weight of a stream and you can say >>>>> that a stream depends on another stream. Neither of those are what I >>>>> want. I simply want to specify priorities of a bunch of requests. How >>>>> would I do that in HTTP 2.0? >>>>> >>>> >>>> Weight is exactly what you want: >>>> http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-5.3.2 >>>> >>>> "A stream that is not dependent on any other stream is given a stream >>>> dependency of 0x0. In other words, the non-existent stream 0 forms >>>> the root of the tree." >>>> >>>> All dependent streams are allocated an integer weight between 1 to >>>> 256 (inclusive)... Streams with the same parent SHOULD be allocated >>>> resources >>>> proportionally based on their weight. " >>>> >>>> In other words, if you don't care about dependencies, then don't assign >>>> the parent. Doing so will make all streams children of the root of the tree >>>> (0x0), and from there you can use weights to assign relative priority. >>>> >>>> Hope that makes sense. >>>> >>>> ig >>>> >>>> >>>> >>>> >>> >>> >>> -- >>> Chad Austin >>> http://chadaustin.me >>> >> >> > > > -- > Chad Austin > http://chadaustin.me >