Re: [whatwg] Expose XMLHttpRequest [Fetch?] priority
I replied on Friday night, but exceeded the 40 KB mailing list limit, and it has not been moderated through yet. So, replying again: On Tue, Oct 14, 2014 at 10:02 AM, Ilya Grigorik igrigo...@gmail.com wrote: On Thu, Oct 9, 2014 at 12:12 PM, Chad Austin caus...@gmail.com wrote: 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) Of course priorities are advisory. :) I don't need strict response ordering. I simply want to simultaneously maximize bandwidth utilization but also, when possible, have the server transmit bytes in the desired order. This is not an unreasonable request either: nginx backed by Varnish, assuming Varnish cache hits (~1ms latency), and assuming the connection is bandwidth-constrained, will send stream frames in approximately priority order. nginx's SPDY implementation is five small C files, and it prioritizes streams and frames with a very simple priority queue implementation. So while priority is advisory, it's also very important for achieving good performance, and it will also be effective in practice. If HTTP 2 servers don't prioritize, they run the risk of regressing performance relative to HTTP. This is because browsers currently prioritize HTTP behind the scenes with a priority queue. *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. Except it would be a linked list instead of a tree. Per Martin Thomson in http://lists.w3.org/Archives/Public/ietf-http-wg/2014OctDec/0164.html, We can't express a dependency on multiple resources, except by creating a linear chain: B2 - B1 - A2 - A1 - 0. In the use case described, managing priorities numerically is much simpler. If three resources A0, A1, A2 have priority 7, and resources B0, B1, and B2 have priority 6, and resource C has priority 5, then it's not a tree. It's a linked list: C - B2 - B1 - B0 - A2 - A1 - A0 - 0. (C - B0 - B2 - B1 - A1 - A2 - A0 - 0 would also be a fine ordering, as the sequencing within each level does not matter.) 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. Again
Re: [whatwg] Preloading and deferred loading of scripts and other resources
On Tue, Oct 7, 2014 at 6:50 PM, Ilya Grigorik igrigo...@gmail.com wrote: On Thu, Sep 11, 2014 at 7:55 PM, Ryosuke Niwa rn...@apple.com wrote: On Sep 8, 2014, at 10:54 PM, Ilya Grigorik igrigo...@gmail.com wrote: On Mon, Sep 8, 2014 at 7:59 PM, Ian Hickson i...@hixie.ch wrote: The platform is missing a lower-level primitive (declarative and imperative) that is able to explain resource loading with the same expressive power as requests initiated by the browser itself. That isn't a problem. I don't follow. To me that *is* the core problem that we should solve first and ship as soon as possible: if we keep the surface area low, we can ship it quickly and let developers experiment and move the platform forward. Adding more layers of higher-level APIs only slows the deployment process. What problem(s) are those developers going to solve with such a low level API other than the use cases A through Z listed here? Responding to Ryosuke (I wasn't on the list then), a low level API is exactly what's missing. IMO, the idea that browsers should provide convenient, high-level, spot solutions to some common problems is flawed. Instead, the browser should expose the lowest-level, most-capable APIs and let libraries sort out the convenience and common idioms. It's less work for browser vendors and empowers library authors and the developer community. I want to be able to fill a page with a thousand img tags and specify that they download in order of distance from the viewport. I want to be able to set priorities of XMLHttpRequests. I want to be able to set XHR priorities relative to image loads (that actually came up _today_ in profiling our application). I want to be able to deprioritize arbitrary resources after first paint. I want to adjust priorities as the application is being used. In short, I agree 100% with Ilya: Instead of hypothesizing about use cases, the web is better-served by exposing the primitive features of the web platform, which lets library authors and web developers decide for themselves how to take advantage of them. Cheers, Chad -- Chad Austin Technical Director, IMVU http://chadaustin.me
Re: [whatwg] Expose XMLHttpRequest [Fetch?] priority
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 * 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.) *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 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; *What about exposing weights?* The only use case I've heard for HTTP 2 stream weights is when you have a pile of progressive images on a page. In almost all other cases, it's better to download some resources sooner rather than have a bunch partially-downloaded. Should I write a document with a formal API proposal including rationale or is this thread sufficient? Thanks, Chad 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
[whatwg] Expose XMLHttpRequest [Fetch?] priority
Hi all, I posted the following message to WebApps, but Anne van Kesteren suggested that I instead post to WHATWG, and generalize my request to anything that supports Fetch. When reading below, feel free to interpret XMLHttpRequest in the broadest sense. The proposal follows: *** I would like to see a priority field added to XMLHttpRequest. Mike Belshe's proposal here is a great start: http://www.mail-archive.com/public-webapps@w3.org/msg08218.html *Motivation* Browsers already prioritize network requests. By giving XMLHttpRequest access to the same machinery, the page or application can reduce overall latency and make better use of available bandwidth. I wrote about our specific use case (efficiently streaming hundreds of 3D assets into WebGL) in detail at http://chadaustin.me/2014/08/web-platform-limitations-xmlhttprequest-priority/ Gecko appears to support a general 32-bit priority: http://lxr.mozilla.org/mozilla-central/source/xpcom/threads/nsISupportsPriority.idl and http://lxr.mozilla.org/mozilla-central/source/netwerk/protocol/http/HttpBaseChannel.cpp#45 Chrome appears to be limited to five priorities: https://code.google.com/p/chromium/codesearch#chromium/src/net/base/request_priority.hsq=package:chromiumtype=csrcl=1411964872 but seems to have a fairly general priority queue implementation, so increasing the number of priorities is likely straightforward. https://code.google.com/p/chromium/codesearch#chromium/src/content/browser/loader/resource_scheduler.ccsq=package:chromiumtype=csrcl=1411964872l=206 SPDY exposes 3 bits of priority per stream. *Proposal* Add a numeric priority property to XMLHttpRequest. It is a 3-bit integer from 0 to 7. Default to 3. 0 is most important. Why integers and not strings, as others have proposed? Because priority arithmetic is convenient. For example, in our use case, we might say The top bit is set by whether an asset is high-resolution or low-resolution. Low-resolution assets would be loaded first. The bottom two bits are used to group request priorities by object. The 3D scene might be the most important resource, followed by my avatar, followed by closer objects, followed by farther objects. Note that, with a very simple use case, we've just consumed all three bits. There's some vague argument that having fewer priorities makes implementing prioritization easier, but as we've seen, the browsers just have a priority queue anyway. Allow priorities to change after send() is called. The browser may ignore this change. It could also ignore the priority property entirely. I propose XMLHttpRequest priority not be artificially limited to a range of priorities relative to other resources the browser might initiate. That is, the API should expose the full set of priorities the browser supports. If my application wants to prioritize an XHR over some browser-initiated request, it should be allowed to do so. The more control over priority available, the better a customer experience can be built. For example, at the logical extreme, fine-grained priority levels and mutable priority values would allow dynamically streaming and reprioritizing texture mip levels as objects approach the camera. If there's enough precision, the application could set priority of an object to the distance from the camera. Or, in a non-WebGL scenario, an image load's priority could be set to the distance from the current viewport. I believe this proposal is very easy to implement: just plumb the priority value through to the prioritizing network layer browsers already implement. What will it take to get this added to the spec? -- Chad Austin http://chadaustin.me
Re: [whatwg] Expose XMLHttpRequest [Fetch?] priority
On Wed, Oct 1, 2014 at 11:02 AM, Ilya Grigorik i...@igvita.com wrote: On Wed, Oct 1, 2014 at 10:54 AM, Chad Austin caus...@gmail.com wrote: I believe this proposal is very easy to implement: just plumb the priority value through to the prioritizing network layer browsers already implement. What will it take to get this added to the spec? 0-7 priority is not sufficient. See previous discussion / proposal: http://lists.w3.org/Archives/Public/public-whatwg-archive/2014Aug/0081.html I would LOVE to have more bits of priority. :) Our particular use case would be satisfied by 7, but if priority was a general 32-bit integer, we would take full advantage of that. I do not understand how to map desired 3D asset priorities onto the HTTP 2.0 dependency graph. We don't have a set of dependent resources - just a priority for each one. Does HTTP 2.0's dependency graph + weights system allow traditional priority semantics? That is, higher-priority resources would be serviced before lower-priority resources, unless resource capacity remains available. I intend to ask on the HTTP-BIS mailing list, but perhaps somebody here who is more caught up on HTTP 2.0 can explain it to me... Thanks, -- Chad Austin http://chadaustin.me
Re: [whatwg] Expose XMLHttpRequest [Fetch?] priority
On Wed, Oct 1, 2014 at 7:24 PM, Ilya Grigorik igrigo...@gmail.com wrote: On Wed, Oct 1, 2014 at 4:48 PM, Chad Austin caus...@gmail.com wrote: Does HTTP 2.0's dependency graph + weights system allow traditional priority semantics? That is, higher-priority resources would be serviced before lower-priority resources, unless resource capacity remains available. Yes, that's exactly how its defined. See: http://tools.ietf.org/html/draft-ietf-httpbis-http2-14#section-5.3 Hi Ilya, 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? Thanks for any clarification you can provide, -- Chad Austin http://chadaustin.me
Re: [whatwg] Expose XMLHttpRequest [Fetch?] priority
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. 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. Does that make sense? Is there anything I can clarify? p.s. I believe it's theoretically possible for an HTTP 2.0 client to map priorities onto stream dependencies, but it seems like the implementation would require a great deal of additional complexity. That is, a stream would be required for every possible priority level. Assume set of streams N at priority P and set of streams M at priority P+2. All of N (streams of priority P) would need to depend on an arbitrary stream in M (priority P+2). When the stream at priority P+2 is closed, the client would need to reattach all of N to another arbitrary stream in M. The addition of a new stream at priority P+1 would require reattaching everything in N (priority P) to the new stream. p.p.s. I asked a friend who stays relatively up-to-date with HTTP 2.0 on whether it's possible to implement SPDY-like priority on HTTP 2.0. His conclusion was yes, with stream dependencies, but it would require the client to do a lot of work, and that feedback should go to ietf-http-wg@ To that end, I posted the following: http://lists.w3.org/Archives/Public/ietf-http-wg/2014OctDec/0016.html 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