Flow Control Fixes.
- Fix default window size
- Allow force-sending specific http2 settings
- Force send default window size always on connection (to avoid []
- Default to using a larger connection window (but keep the per-stream limit small)
- Initialize window sizes per the settings frame received
- Be more aggressive in updating flow control windows (send at 1/4 usage, not 1/2 usage)
Change on 2014/12/07 by ctiller <ctiller@google.com>
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=81534395
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index e6629ac..8d73bd8 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -56,7 +56,8 @@
#include <grpc/support/string.h>
#include <grpc/support/useful.h>
-#define DEFAULT_WINDOW 65536
+#define DEFAULT_WINDOW 65535
+#define DEFAULT_CONNECTION_WINDOW_TARGET (1024 * 1024)
#define MAX_WINDOW 0x7fffffffu
#define CLIENT_CONNECT_STRING "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
@@ -190,12 +191,14 @@
/* settings */
gpr_uint32 settings[NUM_SETTING_SETS][GRPC_CHTTP2_NUM_SETTINGS];
- gpr_uint8 sent_local_settings;
- gpr_uint8 dirtied_local_settings;
+ gpr_uint32 force_send_settings; /* bitmask of setting indexes to send out */
+ gpr_uint8 sent_local_settings; /* have local settings been sent? */
+ gpr_uint8 dirtied_local_settings; /* are the local settings dirty? */
/* window management */
gpr_uint32 outgoing_window;
gpr_uint32 incoming_window;
+ gpr_uint32 connection_window_target;
/* deframing */
deframe_transport_state deframe_state;
@@ -383,6 +386,7 @@
t->is_client = is_client;
t->outgoing_window = DEFAULT_WINDOW;
t->incoming_window = DEFAULT_WINDOW;
+ t->connection_window_target = DEFAULT_CONNECTION_WINDOW_TARGET;
t->deframe_state = is_client ? DTS_FH_0 : DTS_CLIENT_PREFIX_0;
t->expect_continuation_stream_id = 0;
t->pings = NULL;
@@ -415,6 +419,9 @@
}
}
t->dirtied_local_settings = 1;
+ /* Hack: it's common for implementations to assume 65536 bytes initial send
+ window -- this should by rights be 0 */
+ t->force_send_settings = 1 << GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
t->sent_local_settings = 0;
/* configure http2 the way we like it */
@@ -422,6 +429,7 @@
push_setting(t, GRPC_CHTTP2_SETTINGS_ENABLE_PUSH, 0);
push_setting(t, GRPC_CHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 0);
}
+ push_setting(t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, DEFAULT_WINDOW);
if (channel_args) {
for (i = 0; i < channel_args->num_args; i++) {
@@ -506,8 +514,10 @@
grpc_chttp2_stream_map_add(&t->stream_map, s->id, s);
}
- s->outgoing_window = DEFAULT_WINDOW;
- s->incoming_window = DEFAULT_WINDOW;
+ s->outgoing_window =
+ t->settings[PEER_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
+ s->incoming_window =
+ t->settings[SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE];
s->write_closed = 0;
s->read_closed = 0;
s->cancelled = 0;
@@ -812,9 +822,10 @@
if (t->dirtied_local_settings && !t->sent_local_settings) {
gpr_slice_buffer_add(
- &t->outbuf, grpc_chttp2_settings_create(t->settings[SENT_SETTINGS],
- t->settings[LOCAL_SETTINGS],
- GRPC_CHTTP2_NUM_SETTINGS));
+ &t->outbuf, grpc_chttp2_settings_create(
+ t->settings[SENT_SETTINGS], t->settings[LOCAL_SETTINGS],
+ t->force_send_settings, GRPC_CHTTP2_NUM_SETTINGS));
+ t->force_send_settings = 0;
t->dirtied_local_settings = 0;
t->sent_local_settings = 1;
}
@@ -845,7 +856,9 @@
/* for each stream that wants to update its window, add that window here */
while ((s = stream_list_remove_head(t, WINDOW_UPDATE))) {
- gpr_uint32 window_add = DEFAULT_WINDOW - s->incoming_window;
+ gpr_uint32 window_add =
+ t->settings[LOCAL_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] -
+ s->incoming_window;
if (!s->read_closed && window_add) {
gpr_slice_buffer_add(&t->outbuf,
grpc_chttp2_window_update_create(s->id, window_add));
@@ -854,8 +867,8 @@
}
/* if the transport is ready to send a window update, do so here also */
- if (t->incoming_window < DEFAULT_WINDOW / 2) {
- gpr_uint32 window_add = DEFAULT_WINDOW - t->incoming_window;
+ if (t->incoming_window < t->connection_window_target * 3 / 4) {
+ gpr_uint32 window_add = t->connection_window_target - t->incoming_window;
gpr_slice_buffer_add(&t->outbuf,
grpc_chttp2_window_update_create(0, window_add));
t->incoming_window += window_add;
@@ -1017,7 +1030,11 @@
}
static void maybe_join_window_updates(transport *t, stream *s) {
- if (s->allow_window_updates && s->incoming_window < DEFAULT_WINDOW / 2) {
+ if (s->allow_window_updates &&
+ s->incoming_window <
+ t->settings[LOCAL_SETTINGS]
+ [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] *
+ 3 / 4) {
stream_list_join(t, s, WINDOW_UPDATE);
}
}