From a520c179b89610248ef97f614d6b831ccee54c6b Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 12 Oct 2017 15:02:09 +0200 Subject: HTTP/2 protocol handler: tweak receive window sizes We were using the default ones, provided by RFC7540. It appears they are way too restrictive and conservative: when downloading something relatively big, a stream keeps spending the whole session/its own 'recv' windows and thus we have to constantly send WINDOW_UPDATE frames. This significantly slows down our HTTP/2 implementation, making it orders of magnitude slower than HTTP/1.1. To fix this: - We send SETTINGS_INITIAL_WINDOW_SIZE in the first SETTINGS frame to inform our peer that per-stream WINDOW is bigger than 64Kb - We increase the session's receive window size. Task-number: QTBUG-63722 Change-Id: I31312fcfd5f0fc0aee6aaa5d3562cc7d1b931adc Reviewed-by: Edward Welbourne --- src/network/access/http2/http2protocol.cpp | 2 ++ src/network/access/http2/http2protocol_p.h | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src/network/access/http2') diff --git a/src/network/access/http2/http2protocol.cpp b/src/network/access/http2/http2protocol.cpp index 54811aeab0..bb3d6bf575 100644 --- a/src/network/access/http2/http2protocol.cpp +++ b/src/network/access/http2/http2protocol.cpp @@ -216,6 +216,8 @@ Frame default_SETTINGS_frame() // MAX frame size (16 kb), disable/enable PUSH_PROMISE builder.append(Settings::MAX_FRAME_SIZE_ID); builder.append(quint32(maxFrameSize)); + builder.append(Settings::INITIAL_WINDOW_SIZE_ID); + builder.append(initialStreamReceiveWindowSize); builder.append(Settings::ENABLE_PUSH_ID); builder.append(quint32(is_PUSH_PROMISE_enabled())); diff --git a/src/network/access/http2/http2protocol_p.h b/src/network/access/http2/http2protocol_p.h index b26ff0e9f4..c64e960002 100644 --- a/src/network/access/http2/http2protocol_p.h +++ b/src/network/access/http2/http2protocol_p.h @@ -129,10 +129,20 @@ enum Http2PredefinedParameters maxConcurrentStreams = 100 // HTTP/2, 6.5.2 }; -// It's int, it has internal linkage, it's ok to have it in headers - -// no ODR violation is possible. +// These are ints, const, they have internal linkage, it's ok to have them in +// headers - no ODR violation. const quint32 lastValidStreamID((quint32(1) << 31) - 1); // HTTP/2, 5.1.1 +// The default size of 64K is too small and limiting: if we use it, we end up +// sending WINDOW_UPDATE frames on a stream/session all the time, for each +// 2 DATE frames of size 16K (also default) we'll send a WINDOW_UPDATE frame +// for a given stream and have a download speed order of magnitude lower than +// our own HTTP/1.1 protocol handler. We choose a bigger window size (normally, +// HTTP/2 servers are not afraid to immediately set it to possible max anyway) +// and split this window size between our concurrent streams. +const qint32 initialSessionReceiveWindowSize = defaultSessionWindowSize * 10000; +const qint32 initialStreamReceiveWindowSize = initialSessionReceiveWindowSize / maxConcurrentStreams; + extern const Q_AUTOTEST_EXPORT char Http2clientPreface[clientPrefaceLength]; void prepare_for_protocol_upgrade(QHttpNetworkRequest &request); -- cgit v1.2.3