W3C home > Mailing lists > Public > ietf-http-wg@w3.org > October to December 2013

Re: Restarting the discussion on HTTP/2 stream priorities

From: Peter Lepeska <bizzbyster@gmail.com>
Date: Sun, 3 Nov 2013 15:21:48 -0800
Message-ID: <CANmPAYFSOggiM8dKbWVGe3PPjMCuK1jDx0jERMsbZxn8wvkK_Q@mail.gmail.com>
To: William Chan (陈智昌) <willchan@chromium.org>
Cc: HTTP Working Group <ietf-http-wg@w3.org>, Martin Thomson <martin.thomson@gmail.com>
Yes I was assuming that. Let me think on the two tab example you give a
little more.

Thanks,

Peter


On Sun, Nov 3, 2013 at 1:30 PM, William Chan (陈智昌) <willchan@chromium.org>wrote:

> I think you're assuming that all streams in a connection belong to a
> single webpage load. Let me know if not, and I can explain further.
> On Nov 3, 2013 9:04 AM, "Peter Lepeska" <bizzbyster@gmail.com> wrote:
>
>> Right. But my point is that an extremely simple scheme, where the browser
>> just indicates that an object is blocking or not, gets you to the same
>> place as the dependency scheme.
>>
>> Peter
>>
>>
>> On Sun, Nov 3, 2013 at 8:54 AM, Martin Thomson <martin.thomson@gmail.com>wrote:
>>
>>> The intent would be to use ordering (i.e. dependencies) for this
>>> scenario, not "priorities" (aka weights).
>>>
>>>
>>> On 3 November 2013 07:37, <bizzbyster@gmail.com> wrote:
>>>
>>>> Going through your example, would the prioritization at any instant be
>>>> any different if you simply assigned two priorities -- high for resources
>>>> that are blocking (the .js and the .css in your example) and low for
>>>> resources that are non-blocking (the .jpgs)?
>>>>
>>>> Sorry if I'm missing something but it doesn't seem like it to me.
>>>>
>>>> Peter
>>>>
>>>> On Oct 28, 2013, at 3:45 PM, William Chan (陈智昌) <willchan@chromium.org>
>>>> wrote:
>>>>
>>>> On Mon, Oct 28, 2013 at 3:34 PM, Martin Thomson <
>>>> martin.thomson@gmail.com> wrote:
>>>>
>>>>> On 28 October 2013 14:32, William Chan (陈智昌) <willchan@chromium.org>
>>>>> wrote:
>>>>> > I think that the second point is far more controversial and requires
>>>>> more
>>>>> > discussion.
>>>>>
>>>>> It may be the case that you find the first issue compelling enough
>>>>> that a change of some form is justified regardless of what you think
>>>>> on the second :)
>>>>>
>>>>> Of course, I think that there are some significant problems with the
>>>>> proposal, most of which I think that you will find are easy to fix.
>>>>>
>>>>> The first is largely procedural.  I've have people complain about the
>>>>> use of references to documents like the above for archival and IPR
>>>>> reasons.  Maybe copying and pasting the entirety of that document to
>>>>> an email will address those concerns.  Maybe it will also help you
>>>>> understand that it is a little wordy and that perhaps the essence of
>>>>> your proposal could be made more succinctly :)
>>>>>
>>>>
>>>> I have to confess that I heard complaints but never understood the
>>>> reasoning behind them. If it's archival/IPR, I'm perfectly happy to
>>>> copy/paste the document into email. These concerns aren't obvious to me as
>>>> I'm a relative newb to IETF stuff.
>>>>
>>>> As far as the proposal's wordiness, I mostly view it as a straw man to
>>>> ignite discussion. I'm completely expecting that it will be ripped apart :)
>>>> I'm hoping to rely heavily on editors to make it much more succinct once we
>>>> reach some rough consensus. Or perhaps this was a subtle play on your part
>>>> to get me to do better editorial work before sending it to the group :)
>>>>
>>>> I'll give others a chance to discuss other points first. I don't want
>>>> to yell more loudly than others anymore than I already do.
>>>>
>>>>
>>>>>
>>>>> The second is that the idea of prioritization between separate trees
>>>>> isn't really described as being prioritization.  I think that what you
>>>>> want to do is a proportional allocation of resources between those
>>>>> trees, so a term like "weight" is probably more accurate.  You even
>>>>> use that word later.  (Oh crap, I just realized that this is a classic
>>>>> case of "the names aren't important, the standards committee always
>>>>> changes them anyway" scenario, sorry.)
>>>>>
>>>>> Probably more substantially, you need to be a little more concrete
>>>>> when it comes to requirements for managing placeholders and garbage
>>>>> collection.
>>>>>
>>>>> The settings seem like over-engineering to me.  I'm sure that a server
>>>>> implementation can arrive at a reasonable set of behaviours that
>>>>> doesn't degrade too badly for their common workloads without settings
>>>>> being exchanged.  When it comes to resource exhaustion, I think that
>>>>> it's probably more appropriate to deal with those in the DoS
>>>>> considerations than with settings.
>>>>>
>>>>> On the over-engineering theme, the idea that you can reprioritize
>>>>> multiple streams with a single PRIORITY frame concerns me.  That's
>>>>> going to mess with intermediaries of all sorts.  The cost of a
>>>>> PRIORITY frame for each stream is 4 bytes per stream, but then you
>>>>> weren't going to bother with that anyway.
>>>>>
>>>>> Please consider placing default values on priority.  Since you are
>>>>> only going to be able to provide either a dependency or a weight, the
>>>>> complementary item is going to inherit a default.
>>>>>
>>>>
>>>> I'm copy/pasting the doc here:
>>>> Proposal for Stream Dependencies in SPDY
>>>> Draft 1
>>>> Last Updated: 26 October 2012
>>>>
>>>> This document proposes changes to the SPDY protocol to support stream
>>>> dependencies. During a pageload, the server uses dependencies to
>>>> improve performance by allocating bandwidth capacity to the most important
>>>> resource transfers first.
>>>>
>>>> The remainder of this document describes the motivation<https://docs.google.com/a/google.com/document/d/1pNj2op5Y4r1AdnsG8bapS79b11iWDCStjCNHo3AWD0g/edit#bookmark=id.dwzsju9gmwit>for dependencies, protocol
>>>> changes<https://docs.google.com/a/google.com/document/d/1pNj2op5Y4r1AdnsG8bapS79b11iWDCStjCNHo3AWD0g/edit#bookmark=kix.hiogy1u6j43a>to support them, and
>>>> examples<https://docs.google.com/a/google.com/document/d/1pNj2op5Y4r1AdnsG8bapS79b11iWDCStjCNHo3AWD0g/edit#bookmark=id.9awxmm9y20yn>of how those mechanisms can be used by the browser. We conclude with a
>>>> discussion of the client and server policies<https://docs.google.com/a/google.com/document/d/1pNj2op5Y4r1AdnsG8bapS79b11iWDCStjCNHo3AWD0g/edit#bookmark=id.6ii1fem7qsws>afforded by expressing dependency information in SPDY.
>>>>
>>>> (Note that flow control is the subject of a separate document and is
>>>> out of scope here.)
>>>> Motivation
>>>> In SPDY today, each stream has a priority (0–7) chosen by the client
>>>> upon stream creation. Push streams are
>>>> an exception. The server policy today is to assume push streams are all
>>>> low priority. Push or pull, the priority of a stream cannot be changed once
>>>> created.
>>>>
>>>> Priorities provide hints to the server about which streams are most
>>>> important to the client, but they are poorly suited to several common
>>>> use-cases.
>>>>
>>>>
>>>>    - Specifying an ordering of resource transfers
>>>>    Sharing bandwidth between resource transfers may degrade
>>>>    performance as measured by page-load time, e.g., when transferring two
>>>>    Javascript resources that cannot be executed until transfer is complete, or
>>>>    two video chunks that will be played back-to-back. In these circumstances,
>>>>    the browser may wish to specify an ordering --- HTML before script1.js
>>>>    before script2.js before image.png, for example, or video_chunk1 before
>>>>    video_chunk2 and so on. (Moreover, changing the priority of the HTML
>>>>    transfer itself may benefit performance; e.g., a large blocking script will
>>>>    be interpreted and executed more quickly if it does not compete for
>>>>    bandwidth capacity with a large HTML transfer.)
>>>>
>>>>    With a small number of fixed priorities, the browser is simply
>>>>    unable to express an ordering over many resource transfers, and with a
>>>>    large number of priorities, reordering is costly.
>>>>    - Reacting to document parsing
>>>>    Because the browser's document parser blocks while waiting for
>>>>    script and style resource transfers to complete, many resource requests
>>>>    will be speculative. (For more background, see Tony Gentilcore's
>>>>    excellent summary<http://gent.ilcore.com/2011/01/webkit-preloadscanner.html>of Chrome's implementation of speculative parsing, the preload scanner.)
>>>>    These requests may need to be preempted as the document parser learns of
>>>>    higher priority resources. For example, if a script a.js uses
>>>>    document.write to embed another script, b.js, the transfer of b.jsshould preempt other in-flight resource transfers, as the receipt of
>>>>    b.js blocks page layout. As another example, consider images styled
>>>>    with display: none; once such styling is discovered during parsing,
>>>>    associated image transfers should be deferred to prioritize visible content.
>>>>    - Reacting to user behavior
>>>>    Suppose a SPDY proxy is servicing multiple users. In this case,
>>>>    many tabs (and their associated streams) are multiplexed over the same SPDY
>>>>    connection. Fixed priorities (i.e., unchanging over the lifetime of a
>>>>    stream) preclude reacting to user behavior; e.g., a user may switch among
>>>>    concurrently loading tabs.
>>>>    - Server push
>>>>    No single fixed priority is appropriate for server push. A stream
>>>>    pushing a large image, for example, should have lower priority than JS/CSS.
>>>>    But, when pushing JS/CSS that the browser needs, those stream should have
>>>>    high priority.
>>>>
>>>>
>>>> In sum, for many common scenarios, fixed priorities are not sufficient
>>>> to optimize the allocation of bandwidth among competing requests.
>>>>
>>>> Protocol changes
>>>> To address the limitations of priorities, we propose expressingdependencies among streams.
>>>> Dependencies improve matters in two main ways:
>>>>
>>>>    1. Dependencies more accurately reflect the constraints of the
>>>>    browser.
>>>>    Rendering a page is a streaming process that naturally leads to a
>>>>    series of dependencies among resource transfers. For example, a script may
>>>>    block HTML parsing, and a final layout may depend on an external stylesheet.
>>>>    2. Dependencies can be updated efficiently.
>>>>    The relative importance of streams may change as Javascript
>>>>    executes or a user changes tabs, for example. Dependencies allow the
>>>>    browser to express these changes compactly. If a user changes tabs, for
>>>>    example, the browser may simply signal a change in priority of the tab's
>>>>    dependency root, thereby reducing (or increasing) the bandwidth allocated
>>>>    to all dependent transfers.
>>>>
>>>>
>>>> Dependencies are expressed in two ways: 1) a new dependency field in
>>>> the SYN_STREAM message, and 2) a new REPRI message that updates the
>>>> dependency pointers of existing streams. To allow servers to advertise
>>>> their support for scheduling transfers based on dependencies, we propose a
>>>> new SETTINGS id/value pair. We describe the layout and semantics of
>>>> each in turn.
>>>>
>>>> Note that these protocol changes are defined in terms of the latest
>>>> version of the SPDY draft specification<http://grmocg.github.com/SPDY-Specification/draft-mbelshe-httpbis-spdy-00.html>
>>>> .
>>>>
>>>> SYN_STREAM:
>>>>     0        1        2        3         4        5        6        7
>>>>
>>>> +--------+--------+--------+-|-------+--------+--------+--------+--------+
>>>> | Length(16)      |Flags(8)|1| Stream Id(31)                    |
>>>>    0x1 | ->
>>>>
>>>> +--------+--------+--------+-|-------+--------+--------+--------+--------+
>>>>
>>>>    8        9        10        11     12,13,14..N
>>>> +-+-------+--------+--------+--------+=========================+
>>>> |P| PriOrDep(31)                     | Name/Value Header Block |
>>>> +-+-------+--------+--------+--------+=========================+
>>>>
>>>> Here, the first 8 bytes are the standard control frame header (§2.2.2<http://grmocg.github.com/SPDY-Specification/draft-mbelshe-httpbis-spdy-00.html#ControlFrames>).
>>>> A new 32 bit field replaces the existing SYN_STREAM priority bits (
>>>> §2.6.1<http://grmocg.github.com/SPDY-Specification/draft-mbelshe-httpbis-spdy-00.html#SYN_STREAM>)
>>>> with:
>>>>
>>>>
>>>>    - P: A bit indicating whether the following PriOrDep bits specify a
>>>>    priority (P = 1) or a stream ID (P = 0) on which this new stream
>>>>    depends.
>>>>    - PriOrDep: Depending on the value of P, either the priority of the
>>>>    new stream or a stream ID on which this new stream depends.
>>>>    - The structure and semantics of the Name/Value header block (
>>>>    §2.6.11<http://grmocg.github.com/SPDY-Specification/draft-mbelshe-httpbis-spdy-00.html#HeaderBlock>)
>>>>    are unchanged.
>>>>
>>>>
>>>> P is exclusive; a stream may be assigned a priority or a parent
>>>> dependency upon creation, but not both. There are no constraints of the
>>>> value of PriOrDep; any 31 bit value is valid. Thus, a stream may refer
>>>> to a dependency identifier that does not correspond to any current or
>>>> previous stream ID. This is a deliberate design choice that increases
>>>> flexibility for clients when structuring dependencies, a topic we expand
>>>> upon in the policies section<https://docs.google.com/a/google.com/document/d/1pNj2op5Y4r1AdnsG8bapS79b11iWDCStjCNHo3AWD0g/edit#bookmark=id.6ii1fem7qsws>
>>>> .
>>>>
>>>> Server push streams are assigned an initial parent at the discretion of
>>>> the server. A conformant implementation SHOULD create a dependency on the
>>>> push stream's associated-to-stream-id (§3.3.1<http://grmocg.github.com/SPDY-Specification/draft-mbelshe-httpbis-spdy-00.html#anchor20>
>>>> ).
>>>>
>>>> REPRI:
>>>>     0        1        2        3         4        5        6        7
>>>>
>>>> +--------+--------+--------+-|-------+--------+--------+--------+--------+
>>>> | Length(16)      |Flags(8)|1| Dependency Id(31)                |
>>>>    0xc | ->
>>>>
>>>> +--------+--------+--------+-|-------+--------+--------+--------+--------+
>>>>
>>>>    8        9        10        11
>>>> +-+-------+--------+--------+--------+
>>>> |P| PriOrDep(31)                     | optionally followed by:
>>>> +-+-------+--------+--------+--------+
>>>>
>>>> DependencyPriOrDep pairs, where a DependencyPriOrDep pair is:
>>>>
>>>>
>>>> +-|-------+--------+--------+--------+-|-------+--------+--------+--------+
>>>> |X| Dependency Id (31)               |P| PriOrDep(31)
>>>>                     |
>>>>
>>>> +-|-------+--------+--------+--------+-|-------+--------+--------+--------+
>>>>
>>>> As in SYN_STREAM, the control frame header is standard, followed by a
>>>> P/PriOrDep label indicating an update to the 31 bit Dependency Id specified
>>>> in the header. We relabel the typical Stream Id here as Dependency Idsince a dependency need not correspond to an actual stream. (Recall that
>>>> any 31 bit value is a valid dependency identifier.)
>>>>
>>>> To support batched updates of dependencies, an optional list of
>>>> DependencyPriOrDep pairs with identical semantics may follow. The
>>>> number of such pairs is determined by examining the frame length.
>>>> number-of-pairs = ((length - 12) / 8). (12 required bytes, 8 bytes from
>>>> len(stream_id) + len(PriOrDep))
>>>>
>>>> We expect most streams to have at most a single dependency, but this is
>>>> not a protocol requirement. (Later, we describe scenarios where multiple
>>>> parents may improve efficiency.) If a stream is referenced more than once
>>>> in a single frame, this indicates multiple parents. A server implementation
>>>> which does not support multiple parents MUST use the last referenced
>>>> parent. Clients which send multiple parents thus SHOULD put the most
>>>> important parent last.
>>>>
>>>> SETTINGS:
>>>> Recall that dependencies and priorities are advisory. While servers
>>>> must accept the messages, they are not required to incorporate them into
>>>> scheduling decisions. A client may benefit from knowing a server's level of
>>>> support; e.g., a client may specify priorities only if it knows a server
>>>> will ignore dependencies. To communicate this, we propose a new
>>>> SETTINGS ID/value pair (§2.6.4<http://grmocg.github.com/SPDY-Specification/draft-mbelshe-httpbis-spdy-00.html#SETTINGS>
>>>> ),
>>>>
>>>>
>>>>    - ID 9 - SETTINGS_MAX_CONCURRENT_DEPENDENCY_SCHEDULING_NODES allows
>>>>    the server to indicate resource limits for dependency scheduling, e.g., to
>>>>    limit memory consumption. A value of 0 indicates that the server does not
>>>>    support dependency scheduling. (We expect most implementations will select
>>>>    a value greater than or equal to MAX_CONCURRENT_STREAMS.)
>>>>    - ID 10 - SETTINGS_DEPENDENCY_SCHEDULING_NODE_TIMEOUT indicates how
>>>>    long the server will maintain dependency nodes after creation. The value is
>>>>    an interval in milliseconds. This allows the client to estimate if
>>>>    previously created dependency relationships are still available for
>>>>    reference at the server. (We expect conformant implementations to maintain
>>>>    dependencies for at least as long as associated streams are active,
>>>>    although this is not a correctness requirement.)
>>>>
>>>>
>>>> Both of these values are advisory. Servers need not abide by their
>>>> stated values and clients may disregard them. Conformant clients should
>>>> respect the concurrency limit, but servers must be robust to a client that
>>>> exceeds it. Similarly, servers may drop dependency information at any time
>>>> regardless of previous statements made in SETTINGS. This is intended
>>>> to provide flexibility for service policies; e.g., a server may reduce the
>>>> timeout in response to memory pressure or abandon dependency scheduling
>>>> entirely.
>>>>
>>>> Examples / use-cases revisited
>>>> The combination of dependencies and priorities suffices to express
>>>> serialized as well as concurrent transfer schedules. (Both are necessary,
>>>> as we describe below.) But, how should the browser choose dependencies and
>>>> priorities when making requests? This question is best answered
>>>> quantitatively, but as a starting point, we consider the following policy
>>>> in our examples:
>>>>
>>>>
>>>>    1. Resource dependencies are (re)configured to reflect
>>>>    parser-blocking order. The transfer of non-streaming resources is always
>>>>    serialized; i.e., non-async scripts and styling.
>>>>    2. Resources that can be progressively rendered (e.g., images) are
>>>>    transferred concurrently and (re)configured to depend on parser-blocking
>>>>    resource transfers.
>>>>    3. To ensure that the speculative parser can maintain enough
>>>>    in-flight requests to fill pipe between the client and server, page HTML is
>>>>    always a top-level dependency, although it may have lower priority than a
>>>>    resource transfer currently blocking document parsing.
>>>>
>>>>
>>>> When scheduling transfers, we consider a server that allocates
>>>> bandwidth hierarchically within dependency trees and splits equallyamong streams with the same parent.
>>>>
>>>> Concretely, suppose a SPDY connection is multiplexing multiple tabs
>>>> from a user connected to a SPDY proxy, with parent pointers and priorities
>>>> as shown below. (P6, for example, indicates a priority of 6.)
>>>>
>>>> To color in this example, suppose that Tab 1 is the foreground tab,
>>>> loading in parallel with Tab 2 in the background. Thus, its relatively
>>>> higher weight. a.js and b.js are scripts required for the first tab
>>>> and should be transferred serially (as scripts are executed in the order
>>>> they are declared in the document, and are not parsed until transfer
>>>> completes.) Thus, a.js depends on b.js depends on tab1.htm. In the
>>>> background tab, two image transfers share capacity as both can be rendered
>>>> progressively. Both image transfers have the same parent and hence transfer
>>>> concurrently.
>>>>
>>>> Because the streams associated with the transfers of tab1 and tab2 have
>>>> no parent, they are always scheduled before any lower level in their trees.
>>>> But, bandwidth allocation among trees remains proportional as defined by
>>>> the relative priority of roots. For example, if the transfer of
>>>> tab2.htm is in progress and tab1.htm (now complete) is selected, a.jswill be scheduled before
>>>> tab2.htm completes. This process proceeds until all transfers in a
>>>> tree have completed.
>>>>
>>>> As a practical matter, the timeout for pruning nodes in a tree should
>>>> be selected to allow transfers to complete and to allow clients to name
>>>> currently completed parents when defining transfer dependencies.
>>>> Concretely, on a high delay path, a small HTML transfer may be flushed
>>>> entirely by the server before the client receives any data and begins
>>>> making dependent requests for resources embedded in the page.
>>>>
>>>> With these client and server policies in mind, we revisit the
>>>> motivating use-cases described above in greater detail.
>>>>
>>>> - Specifying an ordering of resource transfers
>>>> - Reacting to document parsing
>>>>
>>>> We illustrate the need for both serial dependencies, concurrency, and
>>>> reprioritization in these cases with a simple example.
>>>>
>>>> Suppose site.com has index.htm:
>>>> <html>
>>>> <body>
>>>> <script src="a.js"></script>
>>>> <img src="a.jpg" width="100" height="100"/>
>>>> <img src="b.jpg" width="100" height="100"/>
>>>> <link rel="stylesheet" type="text/css" href="style.css">
>>>> </body>
>>>>
>>>> with a.js:
>>>> document.write('<script src="b.js"></script>');
>>>>
>>>> b.js:
>>>> document.write('<div>blocker</div>');
>>>>
>>>> and style.css:
>>>> div {
>>>>  border: 1px solid #000;
>>>> }
>>>>
>>>> How would this example page be transferred today? As the main HTML is
>>>> received and parsed, a request for a.js will be issued and block the
>>>> document parser. As the remaining HTML streams in, the speculative parser
>>>> will issue requests for a.jpg, b.jpg, and style.css in quick succession.
>>>> Once a.js is received and executed, a request for b.js will be issued,
>>>> which again blocks parsing until received. Visually:
>>>>
>>>>
>>>> This transfer schedule is suboptimal. Page rendering will complete only
>>>> when style.css and b.js have completed, but receiving each of those
>>>> critical resources is slowed by competition for bandwidth capacity with
>>>> bulk data that's not on the critical path (a.jpg and b.jpg).
>>>>
>>>> What we would like is serialized transfer that reflects the document
>>>> parse order with concurrency for nonblocking, streaming resources. More
>>>> specifically, we want to receive: 1) index.html, 2) a.js, 3) b.js, and 4)
>>>> style.css serialized (i.e., with no deliberate sharing of capacity among
>>>> the ordered transfers). After those critical transfers have completed,
>>>> a.jpg and b.jpg should be transferred concurrently (as they may be
>>>> displayed progressively.)
>>>>
>>>> Folding in the protocol mechanisms described above:
>>>>
>>>>
>>>> In the figure, each resource request corresponds to a new SPDY stream
>>>> with the form ID: reqest (PriOrDep). In more detail:
>>>>
>>>>
>>>>    - The SYN_STREAM for the index.htm request has a parent indicating
>>>>    a default priority (3) and a stream id of 1.
>>>>    - The document parser is blocked once the external script a.js is
>>>>    parsed. At this point, the speculative  parser looks ahead and creates new
>>>>    streams for a.jpg, b.jpg in parse order. a.jpg and b.jpg can be
>>>>    progressively rendered, so their transfer is concurrent (same parent, 2,
>>>>    corresponding to a.js).
>>>>    - When the parser encounters style.css, back-to-back control
>>>>    messages are sent to create the stream and update the dependencies of the
>>>>    image transfers. Since stylesheets block rendering and cannot be streamed,
>>>>    the image transfers are updated to depend on style.css (P5).
>>>>    - Once a.js completes, the document parser continues, executing
>>>>    a.js and inserting b.js via document.write(), again blocking
>>>>    document parsing on the receipt of b.js. At this point, b.js should preempt
>>>>    all other transfers since it's a non-streaming resource that is blocking
>>>>    page rendering. To this end, the client creates the b.js stream with a.js
>>>>    as its parent (or, equivalently, index.htm). Batched with this
>>>>    SYN_STREAM is another REPRI message rewiring style.css to depend on
>>>>    b.js. This serializes the transfers (modulo the delay associated with
>>>>    message propagation and any transfer buffering delay at the server).
>>>>
>>>>
>>>> This transfer schedule may significantly improve performance. By
>>>> serializing the transfer of resources on the critical path, the browser can
>>>> ensure that resources needed immediately do not compete for bandwidth
>>>> capacity with less important transfers. Yet, the pipe remains full, as a
>>>> queue of requests is maintained in the scheduling tree ready to fill any
>>>> idle capacity with useful data. Where we cannot make an informed scheduling
>>>> decision, we hedge our bets with concurrent transfers by hinting that they
>>>> are peers and letting the server decide what makes the most sense --- as in
>>>> the case of two above the fold images that can be rendered progressively.
>>>>
>>>> Note that this sort of explicit scheduler hinting is not possible in
>>>> HTTP today. Requests, once issued, cannot be reprioritized or reordered on
>>>> a single connection. This results in suboptimal transfer schedules given
>>>> the limitations of HTML lookahead scanning. Yet, lookahead is essential for
>>>> ensuring the concurrency necessary to keep the client <-> server pipe full.
>>>> While the browser might serialize transfers itself, the many small
>>>> transfers typical of pageloads would significantly limit utilization. With
>>>> ordering and reprioritization in SPDY, browsers can jointly optimize both
>>>> the transfer pipeline and resource priority as desired, rather than
>>>> being forced to accept poor utilization or poor transfer schedules.
>>>>
>>>> - Servicing multiple tabs/users over a single SPDY session
>>>> As an illustration of this case, recall the example from our straw-man
>>>> design:
>>>>
>>>>
>>>> Suppose concurrent tabs are loading with a scheduling forest as shown.
>>>> When a user changes tabs, the browser simple sends a REPRI for the
>>>> stream associated with tab2.htm to, say, priority 8. (A batched message
>>>> might also reduce the priority of tab1.htm to weight 3.) Because bandwidth
>>>> allocation decisions are made tree-by-tree and level-by-level, increasing
>>>> the priority of tab2.htm effectively shifts capacity for all resource
>>>> transfers depending on tab1.htm to tab2.htm.
>>>>
>>>> - Server push
>>>> As in client SYN_STREAM messages, server push messages indicate the
>>>> priority and dependencies of a resource as chosen by the server. Much
>>>> like the client, the server is free to adopt prioritization policies to
>>>> improve performance, e.g., by prioritizing pushes of styles over images.
>>>> But, as in our example above, the browser may update the server's choices
>>>> as information about resources needed for parsing is learned. (Again,
>>>> expressed via REPRI messages.)
>>>>
>>>> Policy considerations
>>>> Both priorities and stream dependencies are advisory hints. Browsers
>>>> may adopt sophisticated policies or leave dependencies entirely
>>>> unspecified. Similarly, servers may incorporate dependency hints into very
>>>> sophisticated schedulers or ignore them entirely. The protocol
>>>> mechanisms for encoding dependencies are designed to be simple. But,
>>>> these mechanisms afford a very flexible set of policies depending on how
>>>> browsers and servers use them. This section expands on several policy
>>>> considerations.
>>>>
>>>> Assigning and updating dependencies.
>>>> Updates and overhead
>>>> In our examples, we consider a browser that configures dependencies to
>>>> reflect parser-blocking order for resources, updated as parsing continues.
>>>> We expect this to improve performance, but browsers are free to deviate
>>>> from this policy, and there may be good reasons to do so. For example, if
>>>> the parser-blocking order is highly dynamic (e.g., in response to many JS
>>>> events), the overhead of updating dependencies may not be worth the cost,
>>>> particularly for small transfers. A sophisticated client may base
>>>> dependency update decisions on content-length and/or RTT, restricting
>>>> updates to only those streams likely to benefit from it. Quantitative
>>>> implementation experience will be helpful here.
>>>>
>>>> The overhead of updating dependencies depends in part on the existing
>>>> structure of dependencies. In some scenarios, it may be more efficient to
>>>> introduce placeholder nodes to improve the efficiency of common update
>>>> operations. For example, consider a variant of our earlier example page:
>>>>
>>>> <html>
>>>> <body>
>>>> <script src="a.js"></script> <!-- containing: document.write('<script
>>>> src="b.js"></script>'); -->
>>>> <img src="1.jpg" width="100" height="100"/>
>>>> <img src="2.jpg" width="100" height="100"/>
>>>> <img src="3.jpg" width="100" height="100"/>
>>>> ...
>>>> <img src="10.jpg" width="100" height="100"/>
>>>> </body>
>>>>
>>>> In this example, the speculative parser might create 10 streams
>>>> depending on the JS transfer; i.e.,
>>>>
>>>> But, once a.js is executed, the transfer of b.js should preempt all
>>>> image transfers; i.e.,
>>>>
>>>> Transitioning between these dependency structures requires sending
>>>> REPRI messages for each image. Because updating the dependencies of
>>>> images is common, a client might create all image streams with a
>>>> placeholder dependency, yielding an initial configuration of:
>>>> With such an initial configuration, updating the dependencies of the
>>>> images to the stream associated with b.js can be accomplished with a single
>>>> REPRI message updating the placeholder.
>>>>
>>>> Multiple parents
>>>>
>>>> ...
>
>
Received on Sunday, 3 November 2013 23:22:18 UTC

This archive was generated by hypermail 2.3.1 : Tuesday, 1 March 2016 11:11:19 UTC