New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 668298 link

Starred by 5 users

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: ----
Pri: 3
Type: Bug



Sign in to add a comment

Update priorities of pushed streams

Project Member Reported by tombergan@chromium.org, Nov 23 2016

Issue description

Over-eager servers can make poor use of HTTP/2 push: they might push low-priority resources interleaved with high-priority resources, or worse, they might push resources that are not needed at all. I propose guarding against such servers by updating priorities of push streams. Specifically:

1. On receiving a push promise for a resource that is not cached ( crbug.com/232040 ), the pushed stream will be assigned an IDLE priority. Chrome will communicate this to the server using an appropriate PRIORITY frame.

2. When a pushed stream is matched to a request, if the stream is still open, then the pushed stream's priority will be updated to match the request's priority. Chrome will communicate this update using appropriate PRIORITY frames (one to reassign old children of the pushed stream, and another to move the pushed stream).

The basic idea is to split pushed streams into "speculative" and "desired" groups. A pushed stream starts as speculative, then becomes desired once it matches an actual request. Speculative streams have IDLE priority to discourage the server from scheduling them unless there are no other outstanding requests.

I pitched this idea (offline) to rdsmith and bnc, who agreed this idea sounds good. Note also that Firefox does something similar (to my knowledge), where pushed streams initially have "speculative" priority (defined here: http://bitsup.blogspot.com/2015/01/http2-dependency-priorities-in-firefox.html) but are upgraded once they match an actual request.

The implementation of parts 1 and 2 is roughly:

1. In OnPushPromise, we pass ConvertRequestPriorityToSpdyPriority(IDLE) to TryCreatePushedStream. Then, if the stream is created, TryCreatePushStream will update SpdySession::priority_dependency_state_ and send a PRIORITY update, similar to Http2PriorityDependencies::OnStreamSynSent.

2. In SpdySession::GetPushStream, if a matching pushed stream is found and the stream is still open, the stream's priority is updated and PRIORITY frames are sent.

This can be protected behind finch if desired, although given the relatively low usage of push in the wild, I doubt we'd get much meaningful performance data from a finch experiment. I do plan to run a few manual experiments.

This idea should apply to QUIC as well, although I'm less familiar with that code.
 
Cc: b...@chromium.org rdsmith@chromium.org
Description: Show this description
Project Member

Comment 3 by bugdroid1@chromium.org, Jan 11 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/5d22c18a5718b6e80507a90dae35a6e0ee5a6333

commit 5d22c18a5718b6e80507a90dae35a6e0ee5a6333
Author: tombergan <tombergan@chromium.org>
Date: Wed Jan 11 02:05:35 2017

http2: Update priorities of pushed streams

On receiving a PUSH_PROMISED, the pushed stream is assigned an IDLE
priority because it is "speculative". When the pushed stream matches
an actual request, the stream's priority is updated to match that of
the request.

In addition to unit tests, I tested this against a local HTTP/2 server
that served the following page:
  <html><body>
	  <script type="application/javascript" src="/a.js"></script>
	  <script type="application/javascript" src="/b.js"></script>
	  <script type="application/javascript" src="/c.js"></script>
  </body></html>

The server was configured to push "/b.js" when serving the HTML. I verified
that the server's priority tree went through the following sequence:
1. {html -> b.js}, after receiving the PUSH_PROMISE
2. {html -> a.js -> b.js}, after the preload scanner finds a.js
3. {html -> a.js -> b.js}, after the preload scanner finds b.js
4. {html -> a.js -> b.js -> c.js}, after the preload scanner finds c.js

Before this change, the final priority tree would have been:
{html -> {b.js, {a.js -> c.js}}}

BUG=668298
R=rdsmith@chromium.org,bnc@chromium.org

Review-Url: https://codereview.chromium.org/2596703002
Cr-Commit-Position: refs/heads/master@{#442770}

[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/http/http_network_transaction_unittest.cc
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/log/net_log_event_type_list.h
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/buffered_spdy_framer.cc
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/buffered_spdy_framer.h
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/http2_priority_dependencies.cc
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/http2_priority_dependencies.h
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/http2_priority_dependencies_unittest.cc
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/spdy_http_stream.cc
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/spdy_network_transaction_unittest.cc
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/spdy_session.cc
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/spdy_session.h
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/spdy_session_unittest.cc
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/spdy_stream.cc
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/spdy_stream.h
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/spdy_stream_unittest.cc
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/spdy_test_util_common.cc
[modify] https://crrev.com/5d22c18a5718b6e80507a90dae35a6e0ee5a6333/net/spdy/spdy_test_util_common.h

Cc: ckrasic@chromium.org
This is done for HTTP/2.

+ckrasic

Buck, I believe QUIC is still using integer priorities ... would a similar change as above make sense for QUIC?
Cc: -rdsmith@chromium.org
Status: Assigned (was: Untriaged)
This bug has an owner, thus, it's been triaged. Changing status to "assigned".

Sign in to add a comment