Re: [whatwg] Expose XMLHttpRequest [Fetch?] priority

2014-10-20 Thread Chad Austin
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

2014-10-16 Thread Chad Austin
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

2014-10-09 Thread Chad Austin
 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

2014-10-01 Thread Chad Austin
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

2014-10-01 Thread Chad Austin
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

2014-10-01 Thread Chad Austin
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

2014-10-01 Thread Chad Austin
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