From 5f4264f9a6b891fd032784ef9811c53d4a70bcdd Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 8 Feb 2017 14:53:04 -0800 Subject: [PATCH 01/13] Signal that authority can be compressed in hpack: saves 1 allocation/rpc --- src/core/lib/surface/channel.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/lib/surface/channel.c b/src/core/lib/surface/channel.c index 429dbad7c77..d6acd392c1a 100644 --- a/src/core/lib/surface/channel.c +++ b/src/core/lib/surface/channel.c @@ -128,7 +128,8 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target, } channel->default_authority = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_AUTHORITY, - grpc_slice_from_copied_string(args->args[i].value.string)); + grpc_slice_intern( + grpc_slice_from_static_string(args->args[i].value.string))); } } else if (0 == strcmp(args->args[i].key, GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)) { @@ -144,7 +145,8 @@ grpc_channel *grpc_channel_create(grpc_exec_ctx *exec_ctx, const char *target, } else { channel->default_authority = grpc_mdelem_from_slices( exec_ctx, GRPC_MDSTR_AUTHORITY, - grpc_slice_from_copied_string(args->args[i].value.string)); + grpc_slice_intern( + grpc_slice_from_static_string(args->args[i].value.string))); } } } else if (0 == strcmp(args->args[i].key, From 07e8fb1775b51d178cb46f81da8518d190c4a066 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Thu, 9 Feb 2017 21:36:24 -0800 Subject: [PATCH 02/13] Eliminate CQ freelist --- src/core/lib/iomgr/ev_epoll_linux.c | 11 ------ src/core/lib/iomgr/ev_poll_posix.c | 11 ------ src/core/lib/iomgr/ev_posix.c | 4 --- src/core/lib/iomgr/ev_posix.h | 1 - src/core/lib/iomgr/pollset.h | 3 -- src/core/lib/iomgr/pollset_uv.c | 5 --- src/core/lib/iomgr/pollset_windows.c | 10 ------ src/core/lib/surface/completion_queue.c | 46 +++++-------------------- src/core/lib/surface/completion_queue.h | 3 -- src/core/lib/surface/init.c | 2 -- test/core/internal_api_canaries/iomgr.c | 1 - 11 files changed, 9 insertions(+), 88 deletions(-) diff --git a/src/core/lib/iomgr/ev_epoll_linux.c b/src/core/lib/iomgr/ev_epoll_linux.c index 51842fc2081..fc56843128e 100644 --- a/src/core/lib/iomgr/ev_epoll_linux.c +++ b/src/core/lib/iomgr/ev_epoll_linux.c @@ -1405,16 +1405,6 @@ static void pollset_destroy(grpc_pollset *pollset) { gpr_mu_destroy(&pollset->po.mu); } -static void pollset_reset(grpc_pollset *pollset) { - GPR_ASSERT(pollset->shutting_down); - GPR_ASSERT(!pollset_has_workers(pollset)); - pollset->shutting_down = false; - pollset->finish_shutdown_called = false; - pollset->kicked_without_pollers = false; - pollset->shutdown_done = NULL; - GPR_ASSERT(pollset->po.pi == NULL); -} - static bool maybe_do_workqueue_work(grpc_exec_ctx *exec_ctx, polling_island *pi) { if (gpr_mu_trylock(&pi->workqueue_read_mu)) { @@ -1958,7 +1948,6 @@ static const grpc_event_engine_vtable vtable = { .pollset_init = pollset_init, .pollset_shutdown = pollset_shutdown, - .pollset_reset = pollset_reset, .pollset_destroy = pollset_destroy, .pollset_work = pollset_work, .pollset_kick = pollset_kick, diff --git a/src/core/lib/iomgr/ev_poll_posix.c b/src/core/lib/iomgr/ev_poll_posix.c index ca129322194..21eb62753ef 100644 --- a/src/core/lib/iomgr/ev_poll_posix.c +++ b/src/core/lib/iomgr/ev_poll_posix.c @@ -815,16 +815,6 @@ static void pollset_destroy(grpc_pollset *pollset) { gpr_mu_destroy(&pollset->mu); } -static void pollset_reset(grpc_pollset *pollset) { - GPR_ASSERT(pollset->shutting_down); - GPR_ASSERT(!pollset_has_workers(pollset)); - GPR_ASSERT(pollset->idle_jobs.head == pollset->idle_jobs.tail); - GPR_ASSERT(pollset->fd_count == 0); - pollset->shutting_down = 0; - pollset->called_shutdown = 0; - pollset->kicked_without_pollers = 0; -} - static void pollset_add_fd(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_fd *fd) { gpr_mu_lock(&pollset->mu); @@ -1514,7 +1504,6 @@ static const grpc_event_engine_vtable vtable = { .pollset_init = pollset_init, .pollset_shutdown = pollset_shutdown, - .pollset_reset = pollset_reset, .pollset_destroy = pollset_destroy, .pollset_work = pollset_work, .pollset_kick = pollset_kick, diff --git a/src/core/lib/iomgr/ev_posix.c b/src/core/lib/iomgr/ev_posix.c index 5bb55631d69..95b1d99d757 100644 --- a/src/core/lib/iomgr/ev_posix.c +++ b/src/core/lib/iomgr/ev_posix.c @@ -191,10 +191,6 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, g_event_engine->pollset_shutdown(exec_ctx, pollset, closure); } -void grpc_pollset_reset(grpc_pollset *pollset) { - g_event_engine->pollset_reset(pollset); -} - void grpc_pollset_destroy(grpc_pollset *pollset) { g_event_engine->pollset_destroy(pollset); } diff --git a/src/core/lib/iomgr/ev_posix.h b/src/core/lib/iomgr/ev_posix.h index a589efdeece..1aea7d61f32 100644 --- a/src/core/lib/iomgr/ev_posix.h +++ b/src/core/lib/iomgr/ev_posix.h @@ -64,7 +64,6 @@ typedef struct grpc_event_engine_vtable { void (*pollset_init)(grpc_pollset *pollset, gpr_mu **mu); void (*pollset_shutdown)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure); - void (*pollset_reset)(grpc_pollset *pollset); void (*pollset_destroy)(grpc_pollset *pollset); grpc_error *(*pollset_work)(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker, gpr_timespec now, diff --git a/src/core/lib/iomgr/pollset.h b/src/core/lib/iomgr/pollset.h index 8d9edc8406b..c4b62a27904 100644 --- a/src/core/lib/iomgr/pollset.h +++ b/src/core/lib/iomgr/pollset.h @@ -58,9 +58,6 @@ void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu); * pollset's mutex must be held */ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_closure *closure); -/** Reset the pollset to its initial state (perhaps with some cached objects); - * must have been previously shutdown */ -void grpc_pollset_reset(grpc_pollset *pollset); void grpc_pollset_destroy(grpc_pollset *pollset); /* Do some work on a pollset. diff --git a/src/core/lib/iomgr/pollset_uv.c b/src/core/lib/iomgr/pollset_uv.c index ed3edeee949..5847771108a 100644 --- a/src/core/lib/iomgr/pollset_uv.c +++ b/src/core/lib/iomgr/pollset_uv.c @@ -97,11 +97,6 @@ void grpc_pollset_destroy(grpc_pollset *pollset) { } } -void grpc_pollset_reset(grpc_pollset *pollset) { - GPR_ASSERT(pollset->shutting_down); - pollset->shutting_down = 0; -} - static void timer_run_cb(uv_timer_t *timer) {} grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, diff --git a/src/core/lib/iomgr/pollset_windows.c b/src/core/lib/iomgr/pollset_windows.c index 2a45e708df6..9be73a7ce8e 100644 --- a/src/core/lib/iomgr/pollset_windows.c +++ b/src/core/lib/iomgr/pollset_windows.c @@ -117,16 +117,6 @@ void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, void grpc_pollset_destroy(grpc_pollset *pollset) {} -void grpc_pollset_reset(grpc_pollset *pollset) { - GPR_ASSERT(pollset->shutting_down); - GPR_ASSERT( - !has_workers(&pollset->root_worker, GRPC_POLLSET_WORKER_LINK_POLLSET)); - pollset->shutting_down = 0; - pollset->is_iocp_worker = 0; - pollset->kicked_without_pollers = 0; - pollset->on_shutdown = NULL; -} - grpc_error *grpc_pollset_work(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset, grpc_pollset_worker **worker_hdl, gpr_timespec now, gpr_timespec deadline) { diff --git a/src/core/lib/surface/completion_queue.c b/src/core/lib/surface/completion_queue.c index 1830842d00b..b80656aa8de 100644 --- a/src/core/lib/surface/completion_queue.c +++ b/src/core/lib/surface/completion_queue.c @@ -96,9 +96,6 @@ struct grpc_completion_queue { #define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1)) #define CQ_FROM_POLLSET(ps) (((grpc_completion_queue *)ps) - 1) -static gpr_mu g_freelist_mu; -static grpc_completion_queue *g_freelist; - int grpc_cq_pluck_trace; int grpc_cq_event_timeout_trace; @@ -113,21 +110,6 @@ int grpc_cq_event_timeout_trace; static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc, grpc_error *error); -void grpc_cq_global_init(void) { gpr_mu_init(&g_freelist_mu); } - -void grpc_cq_global_shutdown(void) { - gpr_mu_destroy(&g_freelist_mu); - while (g_freelist) { - grpc_completion_queue *next = g_freelist->next_free; - grpc_pollset_destroy(POLLSET_FROM_CQ(g_freelist)); -#ifndef NDEBUG - gpr_free(g_freelist->outstanding_tags); -#endif - gpr_free(g_freelist); - g_freelist = next; - } -} - grpc_completion_queue *grpc_completion_queue_create(void *reserved) { grpc_completion_queue *cc; GPR_ASSERT(!reserved); @@ -136,22 +118,12 @@ grpc_completion_queue *grpc_completion_queue_create(void *reserved) { GRPC_API_TRACE("grpc_completion_queue_create(reserved=%p)", 1, (reserved)); - gpr_mu_lock(&g_freelist_mu); - if (g_freelist == NULL) { - gpr_mu_unlock(&g_freelist_mu); - - cc = gpr_malloc(sizeof(grpc_completion_queue) + grpc_pollset_size()); - grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu); + cc = gpr_malloc(sizeof(grpc_completion_queue) + grpc_pollset_size()); + grpc_pollset_init(POLLSET_FROM_CQ(cc), &cc->mu); #ifndef NDEBUG - cc->outstanding_tags = NULL; - cc->outstanding_tag_capacity = 0; + cc->outstanding_tags = NULL; + cc->outstanding_tag_capacity = 0; #endif - } else { - cc = g_freelist; - g_freelist = g_freelist->next_free; - gpr_mu_unlock(&g_freelist_mu); - /* pollset already initialized */ - } /* Initial ref is dropped by grpc_completion_queue_shutdown */ gpr_ref_init(&cc->pending_events, 1); @@ -203,11 +175,11 @@ void grpc_cq_internal_unref(grpc_completion_queue *cc) { #endif if (gpr_unref(&cc->owning_refs)) { GPR_ASSERT(cc->completed_head.next == (uintptr_t)&cc->completed_head); - grpc_pollset_reset(POLLSET_FROM_CQ(cc)); - gpr_mu_lock(&g_freelist_mu); - cc->next_free = g_freelist; - g_freelist = cc; - gpr_mu_unlock(&g_freelist_mu); + grpc_pollset_destroy(POLLSET_FROM_CQ(cc)); +#ifndef NDEBUG + gpr_free(cc->outstanding_tags); +#endif + gpr_free(cc); } } diff --git a/src/core/lib/surface/completion_queue.h b/src/core/lib/surface/completion_queue.h index c1cafba5f2c..5d73dd7216e 100644 --- a/src/core/lib/surface/completion_queue.h +++ b/src/core/lib/surface/completion_queue.h @@ -99,7 +99,4 @@ bool grpc_cq_is_non_listening_server_cq(grpc_completion_queue *cc); void grpc_cq_mark_server_cq(grpc_completion_queue *cc); int grpc_cq_is_server_cq(grpc_completion_queue *cc); -void grpc_cq_global_init(void); -void grpc_cq_global_shutdown(void); - #endif /* GRPC_CORE_LIB_SURFACE_COMPLETION_QUEUE_H */ diff --git a/src/core/lib/surface/init.c b/src/core/lib/surface/init.c index b338ac4c486..91bd014a0e5 100644 --- a/src/core/lib/surface/init.c +++ b/src/core/lib/surface/init.c @@ -209,7 +209,6 @@ void grpc_init(void) { grpc_iomgr_init(); grpc_executor_init(); gpr_timers_global_init(); - grpc_cq_global_init(); grpc_handshaker_factory_registry_init(); grpc_security_init(); for (i = 0; i < g_number_of_plugins; i++) { @@ -236,7 +235,6 @@ void grpc_shutdown(void) { gpr_mu_lock(&g_init_mu); if (--g_initializations == 0) { grpc_executor_shutdown(&exec_ctx); - grpc_cq_global_shutdown(); grpc_iomgr_shutdown(&exec_ctx); gpr_timers_global_destroy(); grpc_tracer_shutdown(); diff --git a/test/core/internal_api_canaries/iomgr.c b/test/core/internal_api_canaries/iomgr.c index d73d5c175c9..6fdaf1f9806 100644 --- a/test/core/internal_api_canaries/iomgr.c +++ b/test/core/internal_api_canaries/iomgr.c @@ -105,7 +105,6 @@ static void test_code(void) { grpc_pollset_size(); grpc_pollset_init(NULL, NULL); grpc_pollset_shutdown(NULL, NULL, NULL); - grpc_pollset_reset(NULL); grpc_pollset_destroy(NULL); GRPC_ERROR_UNREF(grpc_pollset_work(NULL, NULL, NULL, gpr_now(GPR_CLOCK_REALTIME), From 7676e9ac9341759c1d71147e94de020d990783c2 Mon Sep 17 00:00:00 2001 From: Yong Ni Date: Tue, 14 Feb 2017 17:35:25 -0800 Subject: [PATCH 03/13] Tue Feb 14 17:35:25 PST 2017 --- tools/internal_ci/linux/grpc_interop.cfg | 40 ++++++++++++++++++++++ tools/internal_ci/linux/grpc_interop.sh | 42 ++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 tools/internal_ci/linux/grpc_interop.cfg create mode 100755 tools/internal_ci/linux/grpc_interop.sh diff --git a/tools/internal_ci/linux/grpc_interop.cfg b/tools/internal_ci/linux/grpc_interop.cfg new file mode 100644 index 00000000000..ecafcf62ae9 --- /dev/null +++ b/tools/internal_ci/linux/grpc_interop.cfg @@ -0,0 +1,40 @@ +#!/bin/bash +# Copyright 2017, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Config file for the internal CI (in protobuf text format) + +# Location of the continuous shell script in repository. +build_file: "grpc/tools/internal_ci/linux/grpc_interop.sh" +timeout_mins: 60 +action { + define_artifacts { + regex: "**/sponge_log.xml" + } +} diff --git a/tools/internal_ci/linux/grpc_interop.sh b/tools/internal_ci/linux/grpc_interop.sh new file mode 100755 index 00000000000..68bb4199e3d --- /dev/null +++ b/tools/internal_ci/linux/grpc_interop.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +# Copyright 2017, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +set -ex + +export LANG=en_US.UTF-8 + +# Enter the gRPC repo root +cd $(dirname $0)/../../.. + +git submodule update --init + +tools/run_tests/run_interop_tests.py -l all -s all --cloud_to_prod --cloud_to_prod_auth --use_docker --http2_interop -t -j 12 $@ || FAILED="true" +tools/run_tests/run_interop_tests.py -l java --use_docker --http2_badserver_interop $@ || FAILED="true" +tools/run_tests/run_interop_tests.py -l python --use_docker --http2_badserver_interop $@ || FAILED="true" From fd2cd7856b55f391d6bb43d2fd39904b0db3b397 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 15 Feb 2017 06:53:51 -0800 Subject: [PATCH 04/13] Possible connection window flow control improvements Instead of incrementally doling out connection level flow control, use the fact that if a stream's initial_window_delta >= 0 then the application has made some commitment to read those bytes. That means that we should target connection level flow control to be: target_incoming_window = sum(stream_incoming_window_delta if stream_incoming_window_delta > 0) + max(0, k * bdp - sum(abs(stream_incoming_window_delta) if stream_incoming_window_delta < 0)) --- .../chttp2/transport/chttp2_transport.c | 12 ++++- .../ext/transport/chttp2/transport/internal.h | 54 +++++++++++++++++-- .../ext/transport/chttp2/transport/parsing.c | 20 ++++--- .../ext/transport/chttp2/transport/writing.c | 18 +++++-- 4 files changed, 83 insertions(+), 21 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 3ee5e976f84..93bae9f7bda 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -569,6 +569,14 @@ static void destroy_stream_locked(grpc_exec_ctx *exec_ctx, void *sp, GRPC_ERROR_UNREF(s->read_closed_error); GRPC_ERROR_UNREF(s->write_closed_error); + if (s->incoming_window_delta > 0) { + GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA( + "destroy", t, s, s->incoming_window_delta); + } else if (s->incoming_window_delta < 0) { + GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA( + "destroy", t, s, -s->incoming_window_delta); + } + GRPC_CHTTP2_UNREF_TRANSPORT(exec_ctx, t, "stream"); GPR_TIMER_END("destroy_stream", 0); @@ -2054,8 +2062,8 @@ static void incoming_byte_stream_update_flow_control(grpc_exec_ctx *exec_ctx, (int64_t)have_already) { write_type = GRPC_CHTTP2_STREAM_WRITE_INITIATE_COVERED; } - GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, incoming_window_delta, - add_max_recv_bytes); + GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA("op", t, s, + add_max_recv_bytes); GRPC_CHTTP2_FLOW_CREDIT_STREAM("op", t, s, announce_window, add_max_recv_bytes); if ((int64_t)s->incoming_window_delta + (int64_t)initial_window_size - diff --git a/src/core/ext/transport/chttp2/transport/internal.h b/src/core/ext/transport/chttp2/transport/internal.h index 075d421dd46..5d41f4bfda6 100644 --- a/src/core/ext/transport/chttp2/transport/internal.h +++ b/src/core/ext/transport/chttp2/transport/internal.h @@ -271,10 +271,6 @@ struct grpc_chttp2_transport { /** data to write next write */ grpc_slice_buffer qbuf; - /** window available to announce to peer */ - int64_t announce_incoming_window; - /** how much window would we like to have for incoming_window */ - uint32_t connection_window_target; /** how much data are we willing to buffer when the WRITE_BUFFER_HINT is set? */ uint32_t write_buffer_size; @@ -328,6 +324,16 @@ struct grpc_chttp2_transport { /** window available for peer to send to us */ int64_t incoming_window; + /** calculating what we should give for incoming window: + we track the total amount of flow control over initial window size + across all streams: this is data that we want to receive right now (it + has an outstanding read) + and the total amount of flow control under initial window size across all + streams: this is data we've read early + we want to adjust incoming_window such that: + incoming_window = total_over - max(bdp - total_under, 0) */ + int64_t stream_total_over_incoming_window; + int64_t stream_total_under_incoming_window; /* deframing */ grpc_chttp2_deframe_transport_state deframe_state; @@ -634,6 +640,44 @@ typedef enum { GRPC_CHTTP2_FLOW_CREDIT_COMMON(phase, dst_context, 0, dst_context, dst_var, \ amount) +#define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE( \ + phase, transport, dst_context) \ + if (dst_context->incoming_window_delta < 0) { \ + transport->stream_total_under_incoming_window += \ + dst_context->incoming_window_delta; \ + } else if (dst_context->incoming_window_delta > 0) { \ + transport->stream_total_over_incoming_window -= \ + dst_context->incoming_window_delta; \ + } + +#define GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE( \ + phase, transport, dst_context) \ + if (dst_context->incoming_window_delta < 0) { \ + transport->stream_total_under_incoming_window -= \ + dst_context->incoming_window_delta; \ + } else if (dst_context->incoming_window_delta > 0) { \ + transport->stream_total_over_incoming_window += \ + dst_context->incoming_window_delta; \ + } + +#define GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA( \ + phase, transport, dst_context, amount) \ + GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport, \ + dst_context); \ + GRPC_CHTTP2_FLOW_DEBIT_STREAM(phase, transport, dst_context, \ + incoming_window_delta, amount); \ + GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \ + dst_context); + +#define GRPC_CHTTP2_FLOW_CREDIT_STREAM_INCOMING_WINDOW_DELTA( \ + phase, transport, dst_context, amount) \ + GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_PREUPDATE(phase, transport, \ + dst_context); \ + GRPC_CHTTP2_FLOW_CREDIT_STREAM(phase, transport, dst_context, \ + incoming_window_delta, amount); \ + GRPC_CHTTP2_FLOW_STREAM_INCOMING_WINDOW_DELTA_POSTUPDATE(phase, transport, \ + dst_context); + #define GRPC_CHTTP2_FLOW_DEBIT_COMMON(phase, transport, id, dst_context, \ dst_var, amount) \ do { \ @@ -752,4 +796,6 @@ void grpc_chttp2_fail_pending_writes(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, grpc_chttp2_stream *s, grpc_error *error); +uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t); + #endif /* GRPC_CORE_EXT_TRANSPORT_CHTTP2_TRANSPORT_INTERNAL_H */ diff --git a/src/core/ext/transport/chttp2/transport/parsing.c b/src/core/ext/transport/chttp2/transport/parsing.c index 24bd93067b3..7ed00522c3e 100644 --- a/src/core/ext/transport/chttp2/transport/parsing.c +++ b/src/core/ext/transport/chttp2/transport/parsing.c @@ -376,15 +376,6 @@ static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx, return err; } - uint32_t target_incoming_window = GPR_MAX( - t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], - 1024); - GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, incoming_window, - incoming_frame_size); - if (t->incoming_window <= target_incoming_window / 2) { - grpc_chttp2_initiate_write(exec_ctx, t, false, "flow_control"); - } - if (s != NULL) { if (incoming_frame_size > s->incoming_window_delta + @@ -402,8 +393,8 @@ static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx, return err; } - GRPC_CHTTP2_FLOW_DEBIT_STREAM("parse", t, s, incoming_window_delta, - incoming_frame_size); + GRPC_CHTTP2_FLOW_DEBIT_STREAM_INCOMING_WINDOW_DELTA("parse", t, s, + incoming_frame_size); if ((int64_t)t->settings[GRPC_SENT_SETTINGS] [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] + (int64_t)s->incoming_window_delta - (int64_t)s->announce_window <= @@ -417,6 +408,13 @@ static grpc_error *update_incoming_window(grpc_exec_ctx *exec_ctx, s->received_bytes += incoming_frame_size; } + uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t); + GRPC_CHTTP2_FLOW_DEBIT_TRANSPORT("parse", t, incoming_window, + incoming_frame_size); + if (t->incoming_window <= target_incoming_window / 2) { + grpc_chttp2_initiate_write(exec_ctx, t, false, "flow_control"); + } + return GRPC_ERROR_NONE; } diff --git a/src/core/ext/transport/chttp2/transport/writing.c b/src/core/ext/transport/chttp2/transport/writing.c index 05e6f59947a..2b9d93cae7c 100644 --- a/src/core/ext/transport/chttp2/transport/writing.c +++ b/src/core/ext/transport/chttp2/transport/writing.c @@ -152,6 +152,17 @@ static bool stream_ref_if_not_destroyed(gpr_refcount *r) { return true; } +uint32_t grpc_chttp2_target_incoming_window(grpc_chttp2_transport *t) { + return (uint32_t)GPR_MAX( + (int64_t)((1u << 31) - 1), + t->stream_total_over_incoming_window + + (int64_t)GPR_MAX( + t->settings[GRPC_SENT_SETTINGS] + [GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE] - + t->stream_total_under_incoming_window, + 0)); +} + bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_chttp2_stream *s; @@ -310,13 +321,12 @@ bool grpc_chttp2_begin_write(grpc_exec_ctx *exec_ctx, /* if the grpc_chttp2_transport is ready to send a window update, do so here also; 3/4 is a magic number that will likely get tuned soon */ - uint32_t target_incoming_window = GPR_MAX( - t->settings[GRPC_SENT_SETTINGS][GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE], - 1024); + uint32_t target_incoming_window = grpc_chttp2_target_incoming_window(t); uint32_t threshold_to_send_transport_window_update = t->outbuf.count > 0 ? 3 * target_incoming_window / 4 : target_incoming_window / 2; - if (t->incoming_window <= threshold_to_send_transport_window_update) { + if (t->incoming_window <= threshold_to_send_transport_window_update && + t->incoming_window != target_incoming_window) { maybe_initiate_ping(exec_ctx, t, GRPC_CHTTP2_PING_BEFORE_TRANSPORT_WINDOW_UPDATE); uint32_t announced = (uint32_t)GPR_CLAMP( From e2894b42d73e56c85bda418b163beb49756f7140 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 15 Feb 2017 08:12:55 -0800 Subject: [PATCH 05/13] Add some tracing --- .../ext/transport/chttp2/transport/chttp2_transport.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/ext/transport/chttp2/transport/chttp2_transport.c b/src/core/ext/transport/chttp2/transport/chttp2_transport.c index 93bae9f7bda..ddbc656b96d 100644 --- a/src/core/ext/transport/chttp2/transport/chttp2_transport.c +++ b/src/core/ext/transport/chttp2/transport/chttp2_transport.c @@ -265,7 +265,7 @@ static void init_transport(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, .gain_d = 0, .initial_control_value = log2(DEFAULT_WINDOW), .min_control_value = -1, - .max_control_value = 22, + .max_control_value = 25, .integral_range = 10}); grpc_chttp2_goaway_parser_init(&t->goaway_parser); @@ -1809,13 +1809,13 @@ static void update_bdp(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t, if (delta == 0 || (bdp != 0 && delta > -1024 && delta < 1024)) { return; } + if (grpc_bdp_estimator_trace) { + gpr_log(GPR_DEBUG, "%s: update initial window size to %d", t->peer_string, + (int)bdp); + } push_setting(exec_ctx, t, GRPC_CHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, bdp); } -/******************************************************************************* - * INPUT PROCESSING - PARSING - */ - static grpc_error *try_http_parsing(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) { grpc_http_parser parser; From 18570ec948bc45c03600fe5b41b79afc53f66bb3 Mon Sep 17 00:00:00 2001 From: Yong Ni Date: Wed, 15 Feb 2017 12:49:32 -0800 Subject: [PATCH 06/13] Wed Feb 15 12:49:32 PST 2017 --- tools/internal_ci/linux/grpc_interop.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/internal_ci/linux/grpc_interop.cfg b/tools/internal_ci/linux/grpc_interop.cfg index ecafcf62ae9..23b83d2f91e 100644 --- a/tools/internal_ci/linux/grpc_interop.cfg +++ b/tools/internal_ci/linux/grpc_interop.cfg @@ -32,7 +32,8 @@ # Location of the continuous shell script in repository. build_file: "grpc/tools/internal_ci/linux/grpc_interop.sh" -timeout_mins: 60 +# grpc_interop tests can take MANY hours to complete. +timeout_mins: 480 action { define_artifacts { regex: "**/sponge_log.xml" From 17342333a8d36bed87fb01cabb5b685e20c31edf Mon Sep 17 00:00:00 2001 From: yongni Date: Wed, 15 Feb 2017 13:19:41 -0800 Subject: [PATCH 07/13] Update grpc_interop.cfg --- tools/internal_ci/linux/grpc_interop.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/internal_ci/linux/grpc_interop.cfg b/tools/internal_ci/linux/grpc_interop.cfg index 23b83d2f91e..9259faf34d5 100644 --- a/tools/internal_ci/linux/grpc_interop.cfg +++ b/tools/internal_ci/linux/grpc_interop.cfg @@ -32,7 +32,7 @@ # Location of the continuous shell script in repository. build_file: "grpc/tools/internal_ci/linux/grpc_interop.sh" -# grpc_interop tests can take MANY hours to complete. +# grpc_interop tests can take 6+ hours to complete. timeout_mins: 480 action { define_artifacts { From 3577f63136e1f1d6e26a00176a0cff6d9b2d9934 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Wed, 15 Feb 2017 22:09:16 +0000 Subject: [PATCH 08/13] Fix and enable logging-format-interpolation lint --- .pylintrc | 3 +-- src/python/grpcio/grpc/_common.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.pylintrc b/.pylintrc index a4f757f9bdd..23375149c7a 100644 --- a/.pylintrc +++ b/.pylintrc @@ -32,7 +32,6 @@ #TODO: Enable simplifiable-if-statement #TODO: Enable no-self-use #TODO: Enable no-member -#TODO: Enable logging-format-interpolation #TODO: Enable dangerous-default-value -disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,simplifiable-if-statement,no-self-use,no-member,logging-format-interpolation,dangerous-default-value +disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,simplifiable-if-statement,no-self-use,no-member,dangerous-default-value diff --git a/src/python/grpcio/grpc/_common.py b/src/python/grpcio/grpc/_common.py index a5f1f38ea97..dd74ba3ab61 100644 --- a/src/python/grpcio/grpc/_common.py +++ b/src/python/grpcio/grpc/_common.py @@ -92,7 +92,7 @@ def decode(b): try: return b.decode('utf8') except UnicodeDecodeError: - logging.exception('Invalid encoding on {}'.format(b)) + logging.exception('Invalid encoding on %s', b) return b.decode('latin1') From 402aca6621e2880b39de68ee98acdf43f6a211da Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Wed, 15 Feb 2017 22:43:52 +0000 Subject: [PATCH 09/13] Fix and enable dangerous-default-value lint The fix is more of an elision and the code in the changed area is reflowed. --- .pylintrc | 3 +-- src/python/grpcio/grpc/_common.py | 43 +++++++++++-------------------- 2 files changed, 16 insertions(+), 30 deletions(-) diff --git a/.pylintrc b/.pylintrc index 23375149c7a..e887b1cdbd2 100644 --- a/.pylintrc +++ b/.pylintrc @@ -32,6 +32,5 @@ #TODO: Enable simplifiable-if-statement #TODO: Enable no-self-use #TODO: Enable no-member -#TODO: Enable dangerous-default-value -disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,simplifiable-if-statement,no-self-use,no-member,dangerous-default-value +disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,simplifiable-if-statement,no-self-use,no-member diff --git a/src/python/grpcio/grpc/_common.py b/src/python/grpcio/grpc/_common.py index dd74ba3ab61..f9accd75a9f 100644 --- a/src/python/grpcio/grpc/_common.py +++ b/src/python/grpcio/grpc/_common.py @@ -148,36 +148,23 @@ def fully_qualified_method(group, method): class CleanupThread(threading.Thread): """A threading.Thread subclass supporting custom behavior on join(). - On Python Interpreter exit, Python will attempt to join outstanding threads - prior to garbage collection. We may need to do additional cleanup, and - we accomplish this by overriding the join() method. - """ - - def __init__(self, - behavior, - group=None, - target=None, - name=None, - args=(), - kwargs={}): + On Python Interpreter exit, Python will attempt to join outstanding threads + prior to garbage collection. We may need to do additional cleanup, and + we accomplish this by overriding the join() method. + """ + + def __init__(self, behavior, *args, **kwargs): """Constructor. - Args: - behavior (function): Function called on join() with a single - argument, timeout, indicating the maximum duration of - `behavior`, or None indicating `behavior` has no deadline. - `behavior` must be idempotent. - group (None): should be None. Reseved for future extensions - when ThreadGroup is implemented. - target (function): The function to invoke when this thread is - run. Defaults to None. - name (str): The name of this thread. Defaults to None. - args (tuple[object]): A tuple of arguments to pass to `target`. - kwargs (dict[str,object]): A dictionary of keyword arguments to - pass to `target`. - """ - super(CleanupThread, self).__init__( - group=group, target=target, name=name, args=args, kwargs=kwargs) + Args: + behavior (function): Function called on join() with a single + argument, timeout, indicating the maximum duration of + `behavior`, or None indicating `behavior` has no deadline. + `behavior` must be idempotent. + args: Positional arguments passed to threading.Thread constructor. + kwargs: Keyword arguments passed to threading.Thread constructor. + """ + super(CleanupThread, self).__init__(*args, **kwargs) self._behavior = behavior def join(self, timeout=None): From a52d3bb39b79039ebc66725773289035f0c002d7 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Wed, 15 Feb 2017 23:00:05 +0000 Subject: [PATCH 10/13] Fix and enable simplifiable-if-statement lint --- .pylintrc | 3 +-- src/python/grpcio/grpc/_auth.py | 7 ++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/.pylintrc b/.pylintrc index e887b1cdbd2..1682488cb4a 100644 --- a/.pylintrc +++ b/.pylintrc @@ -29,8 +29,7 @@ #TODO: Enable too-many-return-statements #TODO: Enable too-many-nested-blocks #TODO: Enable super-init-not-called -#TODO: Enable simplifiable-if-statement #TODO: Enable no-self-use #TODO: Enable no-member -disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,simplifiable-if-statement,no-self-use,no-member +disable=missing-docstring,too-few-public-methods,too-many-arguments,no-init,duplicate-code,invalid-name,suppressed-message,locally-disabled,protected-access,no-name-in-module,unused-argument,fixme,wrong-import-order,no-value-for-parameter,cyclic-import,unused-variable,redefined-outer-name,unused-import,too-many-instance-attributes,broad-except,too-many-locals,too-many-lines,redefined-variable-type,next-method-called,import-error,useless-else-on-loop,too-many-return-statements,too-many-nested-blocks,super-init-not-called,no-self-use,no-member diff --git a/src/python/grpcio/grpc/_auth.py b/src/python/grpcio/grpc/_auth.py index e8a90cf5047..21131f85f17 100644 --- a/src/python/grpcio/grpc/_auth.py +++ b/src/python/grpcio/grpc/_auth.py @@ -48,11 +48,8 @@ class GoogleCallCredentials(grpc.AuthMetadataPlugin): # Hack to determine if these are JWT creds and we need to pass # additional_claims when getting a token - if 'additional_claims' in inspect.getargspec( - credentials.get_access_token).args: - self._is_jwt = True - else: - self._is_jwt = False + self._is_jwt = 'additional_claims' in inspect.getargspec( + credentials.get_access_token).args def __call__(self, context, callback): # MetadataPlugins cannot block (see grpc.beta.interfaces.py) From 73495e3b3507438828d34376fa06fd68db18250e Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Wed, 15 Feb 2017 23:06:30 +0000 Subject: [PATCH 11/13] Ignore python_pylint_venv/. This should have been included in 1a967c31c3a7fbd2d6d5cb6c1e575fdb2d. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 4098106e760..56e4b6d4b43 100644 --- a/.gitignore +++ b/.gitignore @@ -9,6 +9,7 @@ objs cython_debug/ python_build/ python_format_venv/ +python_pylint_venv/ .coverage* .eggs htmlcov/ From b3a1ec2111676d1504e1fdef41fdf8e046c1e283 Mon Sep 17 00:00:00 2001 From: Nathaniel Manista Date: Wed, 15 Feb 2017 23:07:40 +0000 Subject: [PATCH 12/13] Output diff on failed yapf sanity --- tools/distrib/yapf_code.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/distrib/yapf_code.sh b/tools/distrib/yapf_code.sh index 030412ebeb9..007b14810eb 100755 --- a/tools/distrib/yapf_code.sh +++ b/tools/distrib/yapf_code.sh @@ -53,7 +53,7 @@ for dir in $DIRS; do tempdir=`mktemp -d` cp -RT $dir $tempdir $PYTHON -m yapf -i -r -p $exclusion_args $dir - if ! diff -rq $dir $tempdir; then + if ! diff -r $dir $tempdir; then script_result=1 fi rm -rf $tempdir From 891e8162e409b7048297c5b820a399f19f2a020b Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Wed, 15 Feb 2017 23:30:27 -0800 Subject: [PATCH 13/13] Fix escaping in index.html --- tools/run_tests/run_microbenchmark.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/run_tests/run_microbenchmark.py b/tools/run_tests/run_microbenchmark.py index 4e60cce8688..9bcba598b83 100755 --- a/tools/run_tests/run_microbenchmark.py +++ b/tools/run_tests/run_microbenchmark.py @@ -28,6 +28,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import cgi import multiprocessing import os import subprocess @@ -71,11 +72,12 @@ def heading(name): def link(txt, tgt): global index_html - index_html += "

%s

\n" % (tgt, txt) + index_html += "

%s

\n" % ( + cgi.escape(tgt, quote=True), cgi.escape(txt)) def text(txt): global index_html - index_html += "

%s

\n" % txt + index_html += "

%s

\n" % cgi.escape(txt) def collect_latency(bm_name, args): """generate latency profiles"""