aboutsummaryrefslogtreecommitdiffhomepage
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/core/census/BUILD2
-rw-r--r--test/core/channel/BUILD2
-rw-r--r--test/core/channel/channel_stack_test.c16
-rw-r--r--test/core/client_channel/parse_address_test.c116
-rw-r--r--test/core/client_channel/resolvers/dns_resolver_connectivity_test.c2
-rw-r--r--test/core/client_channel/resolvers/dns_resolver_test.c4
-rw-r--r--test/core/client_channel/resolvers/sockaddr_resolver_test.c4
-rw-r--r--test/core/client_channel/uri_fuzzer_test.c5
-rw-r--r--test/core/client_channel/uri_parser_test.c23
-rw-r--r--test/core/compression/BUILD2
-rw-r--r--test/core/end2end/BUILD4
-rw-r--r--test/core/end2end/end2end_tests.h7
-rw-r--r--test/core/end2end/fixtures/h2_http_proxy.c2
-rw-r--r--test/core/end2end/fixtures/http_proxy_fixture.c (renamed from test/core/end2end/fixtures/http_proxy.c)2
-rw-r--r--test/core/end2end/fixtures/http_proxy_fixture.h (renamed from test/core/end2end/fixtures/http_proxy.h)0
-rw-r--r--test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6520142139752448bin0 -> 384 bytes
-rw-r--r--test/core/end2end/tests/filter_call_init_fails.c2
-rw-r--r--test/core/end2end/tests/filter_causes_close.c2
-rw-r--r--test/core/end2end/tests/filter_latency.c4
-rw-r--r--test/core/end2end/tests/network_status_change.c4
-rw-r--r--test/core/end2end/tests/resource_quota_server.c4
-rw-r--r--test/core/end2end/tests/streaming_error_response.c3
-rw-r--r--test/core/fling/fling_stream_test.c81
-rw-r--r--test/core/handshake/BUILD2
-rw-r--r--test/core/iomgr/error_test.c219
-rw-r--r--test/core/iomgr/sockaddr_utils_test.c16
-rw-r--r--test/core/iomgr/tcp_client_uv_test.c7
-rw-r--r--test/core/iomgr/tcp_server_posix_test.c33
-rw-r--r--test/core/iomgr/tcp_server_uv_test.c4
-rw-r--r--test/core/iomgr/udp_server_test.c8
-rw-r--r--test/core/memory_usage/client.c24
-rw-r--r--test/core/security/BUILD2
-rw-r--r--test/core/security/ssl_server_fuzzer.c14
-rw-r--r--test/core/slice/percent_encoding_test.c1
-rw-r--r--test/core/support/BUILD2
-rw-r--r--test/core/support/arena_test.c139
-rw-r--r--test/core/support/cpu_test.c7
-rw-r--r--test/core/surface/BUILD2
-rw-r--r--test/core/transport/BUILD7
-rw-r--r--test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112bin0 -> 172032 bytes
-rw-r--r--test/core/transport/stream_owned_slice_test.c58
-rw-r--r--test/core/util/memory_counters.c48
-rw-r--r--test/core/util/port_server_client.c9
-rw-r--r--test/core/util/trickle_endpoint.c5
-rw-r--r--test/cpp/codegen/compiler_test_golden2
-rw-r--r--test/cpp/common/channel_arguments_test.cc7
-rw-r--r--test/cpp/interop/http2_client.cc2
-rw-r--r--test/cpp/interop/http2_client.h2
-rw-r--r--test/cpp/interop/interop_client.cc4
-rw-r--r--test/cpp/interop/interop_client.h2
-rw-r--r--test/cpp/interop/interop_server.cc4
-rw-r--r--test/cpp/interop/reconnect_interop_client.cc4
-rw-r--r--test/cpp/interop/reconnect_interop_server.cc4
-rw-r--r--test/cpp/microbenchmarks/bm_arena.cc76
-rw-r--r--test/cpp/microbenchmarks/bm_call_create.cc133
-rw-r--r--test/cpp/microbenchmarks/bm_chttp2_hpack.cc14
-rw-r--r--test/cpp/microbenchmarks/bm_closure.cc114
-rw-r--r--test/cpp/microbenchmarks/bm_cq.cc23
-rw-r--r--test/cpp/microbenchmarks/bm_error.cc64
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack.cc1079
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc276
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc197
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack_trickle.cc219
-rw-r--r--test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc205
-rw-r--r--test/cpp/microbenchmarks/bm_metadata.cc62
-rw-r--r--test/cpp/microbenchmarks/bm_pollset.cc254
-rw-r--r--test/cpp/microbenchmarks/fullstack_context_mutators.h158
-rw-r--r--test/cpp/microbenchmarks/fullstack_fixtures.h244
-rw-r--r--test/cpp/microbenchmarks/helpers.cc65
-rw-r--r--test/cpp/microbenchmarks/helpers.h93
-rw-r--r--test/cpp/qps/client.h2
-rw-r--r--test/cpp/qps/client_async.cc4
-rw-r--r--test/cpp/qps/client_sync.cc15
-rw-r--r--test/cpp/qps/driver.h2
-rw-r--r--test/cpp/qps/histogram.h2
-rw-r--r--test/cpp/qps/qps_json_driver.cc1
-rw-r--r--test/cpp/qps/server.h4
-rw-r--r--test/cpp/qps/server_async.cc19
-rw-r--r--test/cpp/qps/server_sync.cc4
-rw-r--r--test/cpp/server/server_builder_test.cc96
-rw-r--r--test/http2_test/http2_server_health_check.py49
-rw-r--r--test/http2_test/http2_test_server.py21
82 files changed, 3063 insertions, 1361 deletions
diff --git a/test/core/census/BUILD b/test/core/census/BUILD
index 9ec48bdfe2..49680ab91f 100644
--- a/test/core/census/BUILD
+++ b/test/core/census/BUILD
@@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+licenses(["notice"]) # 3-clause BSD
+
cc_test(
name = "context_test",
srcs = ["context_test.c"],
diff --git a/test/core/channel/BUILD b/test/core/channel/BUILD
index 42cb468485..c6590465f1 100644
--- a/test/core/channel/BUILD
+++ b/test/core/channel/BUILD
@@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+licenses(["notice"]) # 3-clause BSD
+
cc_test(
name = "channel_args_test",
srcs = ["channel_args_test.c"],
diff --git a/test/core/channel/channel_stack_test.c b/test/core/channel/channel_stack_test.c
index 76bb57346c..af551c4928 100644
--- a/test/core/channel/channel_stack_test.c
+++ b/test/core/channel/channel_stack_test.c
@@ -68,7 +68,7 @@ static void channel_destroy_func(grpc_exec_ctx *exec_ctx,
static void call_destroy_func(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *ignored) {
+ grpc_closure *ignored) {
++*(int *)(elem->channel_data);
}
@@ -139,10 +139,16 @@ static void test_create_channel_stack(void) {
GPR_ASSERT(*channel_data == 0);
call_stack = gpr_malloc(channel_stack->call_stack_size);
- grpc_error *error =
- grpc_call_stack_init(&exec_ctx, channel_stack, 1, free_call, call_stack,
- NULL, NULL, path, gpr_now(GPR_CLOCK_MONOTONIC),
- gpr_inf_future(GPR_CLOCK_MONOTONIC), call_stack);
+ const grpc_call_element_args args = {
+ .call_stack = call_stack,
+ .server_transport_data = NULL,
+ .context = NULL,
+ .path = path,
+ .start_time = gpr_now(GPR_CLOCK_MONOTONIC),
+ .deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC),
+ .arena = NULL};
+ grpc_error *error = grpc_call_stack_init(&exec_ctx, channel_stack, 1,
+ free_call, call_stack, &args);
GPR_ASSERT(error == GRPC_ERROR_NONE);
GPR_ASSERT(call_stack->count == 1);
call_elem = grpc_call_stack_element(call_stack, 0);
diff --git a/test/core/client_channel/parse_address_test.c b/test/core/client_channel/parse_address_test.c
new file mode 100644
index 0000000000..37dd0fba52
--- /dev/null
+++ b/test/core/client_channel/parse_address_test.c
@@ -0,0 +1,116 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/core/ext/client_channel/parse_address.h"
+#include "src/core/lib/iomgr/sockaddr.h"
+
+#include <string.h>
+#ifdef GRPC_HAVE_UNIX_SOCKET
+#include <sys/un.h>
+#endif
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/socket_utils.h"
+#include "test/core/util/test_config.h"
+
+#ifdef GRPC_HAVE_UNIX_SOCKET
+
+static void test_parse_unix(const char *uri_text, const char *pathname) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
+ grpc_resolved_address addr;
+
+ GPR_ASSERT(1 == parse_unix(uri, &addr));
+ struct sockaddr_un *addr_un = (struct sockaddr_un *)addr.addr;
+ GPR_ASSERT(AF_UNIX == addr_un->sun_family);
+ GPR_ASSERT(0 == strcmp(addr_un->sun_path, pathname));
+
+ grpc_uri_destroy(uri);
+ grpc_exec_ctx_finish(&exec_ctx);
+}
+
+#else /* GRPC_HAVE_UNIX_SOCKET */
+
+static void test_parse_unix(const char *uri_text, const char *pathname) {}
+
+#endif /* GRPC_HAVE_UNIX_SOCKET */
+
+static void test_parse_ipv4(const char *uri_text, const char *host,
+ unsigned short port) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
+ grpc_resolved_address addr;
+ char ntop_buf[INET_ADDRSTRLEN];
+
+ GPR_ASSERT(1 == parse_ipv4(uri, &addr));
+ struct sockaddr_in *addr_in = (struct sockaddr_in *)addr.addr;
+ GPR_ASSERT(AF_INET == addr_in->sin_family);
+ GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET, &addr_in->sin_addr, ntop_buf,
+ sizeof(ntop_buf)));
+ GPR_ASSERT(0 == strcmp(ntop_buf, host));
+ GPR_ASSERT(ntohs(addr_in->sin_port) == port);
+
+ grpc_uri_destroy(uri);
+ grpc_exec_ctx_finish(&exec_ctx);
+}
+
+static void test_parse_ipv6(const char *uri_text, const char *host,
+ unsigned short port, uint32_t scope_id) {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
+ grpc_resolved_address addr;
+ char ntop_buf[INET6_ADDRSTRLEN];
+
+ GPR_ASSERT(1 == parse_ipv6(uri, &addr));
+ struct sockaddr_in6 *addr_in6 = (struct sockaddr_in6 *)addr.addr;
+ GPR_ASSERT(AF_INET6 == addr_in6->sin6_family);
+ GPR_ASSERT(NULL != grpc_inet_ntop(AF_INET6, &addr_in6->sin6_addr, ntop_buf,
+ sizeof(ntop_buf)));
+ GPR_ASSERT(0 == strcmp(ntop_buf, host));
+ GPR_ASSERT(ntohs(addr_in6->sin6_port) == port);
+ GPR_ASSERT(addr_in6->sin6_scope_id == scope_id);
+
+ grpc_uri_destroy(uri);
+ grpc_exec_ctx_finish(&exec_ctx);
+}
+
+int main(int argc, char **argv) {
+ grpc_test_init(argc, argv);
+
+ test_parse_unix("unix:/path/name", "/path/name");
+ test_parse_ipv4("ipv4:192.0.2.1:12345", "192.0.2.1", 12345);
+ test_parse_ipv6("ipv6:[2001:db8::1]:12345", "2001:db8::1", 12345, 0);
+ test_parse_ipv6("ipv6:[2001:db8::1%252]:12345", "2001:db8::1", 12345, 2);
+}
diff --git a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
index 3e3401165c..187757d5b3 100644
--- a/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
+++ b/test/core/client_channel/resolvers/dns_resolver_connectivity_test.c
@@ -69,7 +69,7 @@ static grpc_error *my_resolve_address(const char *name, const char *addr,
static grpc_resolver *create_resolver(grpc_exec_ctx *exec_ctx,
const char *name) {
grpc_resolver_factory *factory = grpc_resolver_factory_lookup("dns");
- grpc_uri *uri = grpc_uri_parse(name, 0);
+ grpc_uri *uri = grpc_uri_parse(exec_ctx, name, 0);
GPR_ASSERT(uri);
grpc_resolver_args args;
memset(&args, 0, sizeof(args));
diff --git a/test/core/client_channel/resolvers/dns_resolver_test.c b/test/core/client_channel/resolvers/dns_resolver_test.c
index 9dd5aed091..919a85d58f 100644
--- a/test/core/client_channel/resolvers/dns_resolver_test.c
+++ b/test/core/client_channel/resolvers/dns_resolver_test.c
@@ -43,7 +43,7 @@ static grpc_combiner *g_combiner;
static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- grpc_uri *uri = grpc_uri_parse(string, 0);
+ grpc_uri *uri = grpc_uri_parse(&exec_ctx, string, 0);
grpc_resolver_args args;
grpc_resolver *resolver;
gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string,
@@ -61,7 +61,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
static void test_fails(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- grpc_uri *uri = grpc_uri_parse(string, 0);
+ grpc_uri *uri = grpc_uri_parse(&exec_ctx, string, 0);
grpc_resolver_args args;
grpc_resolver *resolver;
gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string,
diff --git a/test/core/client_channel/resolvers/sockaddr_resolver_test.c b/test/core/client_channel/resolvers/sockaddr_resolver_test.c
index 68831ab7c7..bc4f02c339 100644
--- a/test/core/client_channel/resolvers/sockaddr_resolver_test.c
+++ b/test/core/client_channel/resolvers/sockaddr_resolver_test.c
@@ -57,7 +57,7 @@ void on_resolution_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- grpc_uri *uri = grpc_uri_parse(string, 0);
+ grpc_uri *uri = grpc_uri_parse(&exec_ctx, string, 0);
grpc_resolver_args args;
grpc_resolver *resolver;
gpr_log(GPR_DEBUG, "test: '%s' should be valid for '%s'", string,
@@ -84,7 +84,7 @@ static void test_succeeds(grpc_resolver_factory *factory, const char *string) {
static void test_fails(grpc_resolver_factory *factory, const char *string) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- grpc_uri *uri = grpc_uri_parse(string, 0);
+ grpc_uri *uri = grpc_uri_parse(&exec_ctx, string, 0);
grpc_resolver_args args;
grpc_resolver *resolver;
gpr_log(GPR_DEBUG, "test: '%s' should be invalid for '%s'", string,
diff --git a/test/core/client_channel/uri_fuzzer_test.c b/test/core/client_channel/uri_fuzzer_test.c
index d2e3fb40ea..baadd4fc65 100644
--- a/test/core/client_channel/uri_fuzzer_test.c
+++ b/test/core/client_channel/uri_fuzzer_test.c
@@ -38,6 +38,7 @@
#include <grpc/support/alloc.h>
#include "src/core/ext/client_channel/uri_parser.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
bool squelch = true;
bool leak_check = true;
@@ -47,10 +48,12 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
memcpy(s, data, size);
s[size] = 0;
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_uri *x;
- if ((x = grpc_uri_parse(s, 1))) {
+ if ((x = grpc_uri_parse(&exec_ctx, s, 1))) {
grpc_uri_destroy(x);
}
+ grpc_exec_ctx_finish(&exec_ctx);
gpr_free(s);
return 0;
}
diff --git a/test/core/client_channel/uri_parser_test.c b/test/core/client_channel/uri_parser_test.c
index 5f32d3270c..8a127f72eb 100644
--- a/test/core/client_channel/uri_parser_test.c
+++ b/test/core/client_channel/uri_parser_test.c
@@ -37,29 +37,35 @@
#include <grpc/support/log.h>
+#include "src/core/lib/iomgr/exec_ctx.h"
#include "test/core/util/test_config.h"
static void test_succeeds(const char *uri_text, const char *scheme,
const char *authority, const char *path,
const char *query, const char *fragment) {
- grpc_uri *uri = grpc_uri_parse(uri_text, 0);
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
GPR_ASSERT(uri);
GPR_ASSERT(0 == strcmp(scheme, uri->scheme));
GPR_ASSERT(0 == strcmp(authority, uri->authority));
GPR_ASSERT(0 == strcmp(path, uri->path));
GPR_ASSERT(0 == strcmp(query, uri->query));
GPR_ASSERT(0 == strcmp(fragment, uri->fragment));
+ grpc_exec_ctx_finish(&exec_ctx);
grpc_uri_destroy(uri);
}
static void test_fails(const char *uri_text) {
- GPR_ASSERT(NULL == grpc_uri_parse(uri_text, 0));
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ GPR_ASSERT(NULL == grpc_uri_parse(&exec_ctx, uri_text, 0));
+ grpc_exec_ctx_finish(&exec_ctx);
}
static void test_query_parts() {
{
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
const char *uri_text = "http://foo/path?a&b=B&c=&#frag";
- grpc_uri *uri = grpc_uri_parse(uri_text, 0);
+ grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
GPR_ASSERT(uri);
GPR_ASSERT(0 == strcmp("http", uri->scheme));
@@ -86,12 +92,14 @@ static void test_query_parts() {
GPR_ASSERT(NULL == grpc_uri_get_query_arg(uri, ""));
GPR_ASSERT(0 == strcmp("frag", uri->fragment));
+ grpc_exec_ctx_finish(&exec_ctx);
grpc_uri_destroy(uri);
}
{
/* test the current behavior of multiple query part values */
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
const char *uri_text = "http://auth/path?foo=bar=baz&foobar==";
- grpc_uri *uri = grpc_uri_parse(uri_text, 0);
+ grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
GPR_ASSERT(uri);
GPR_ASSERT(0 == strcmp("http", uri->scheme));
@@ -103,12 +111,14 @@ static void test_query_parts() {
GPR_ASSERT(0 == strcmp("bar", grpc_uri_get_query_arg(uri, "foo")));
GPR_ASSERT(0 == strcmp("", grpc_uri_get_query_arg(uri, "foobar")));
+ grpc_exec_ctx_finish(&exec_ctx);
grpc_uri_destroy(uri);
}
{
/* empty query */
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
const char *uri_text = "http://foo/path";
- grpc_uri *uri = grpc_uri_parse(uri_text, 0);
+ grpc_uri *uri = grpc_uri_parse(&exec_ctx, uri_text, 0);
GPR_ASSERT(uri);
GPR_ASSERT(0 == strcmp("http", uri->scheme));
@@ -119,6 +129,7 @@ static void test_query_parts() {
GPR_ASSERT(NULL == uri->query_parts);
GPR_ASSERT(NULL == uri->query_parts_values);
GPR_ASSERT(0 == strcmp("", uri->fragment));
+ grpc_exec_ctx_finish(&exec_ctx);
grpc_uri_destroy(uri);
}
}
@@ -142,6 +153,8 @@ int main(int argc, char **argv) {
test_succeeds("http:?legit#twice", "http", "", "", "legit", "twice");
test_succeeds("http://foo?bar#lol?", "http", "foo", "", "bar", "lol?");
test_succeeds("http://foo?bar#lol?/", "http", "foo", "", "bar", "lol?/");
+ test_succeeds("ipv6:[2001:db8::1%252]:12345", "ipv6", "",
+ "[2001:db8::1%2]:12345", "", "");
test_fails("xyz");
test_fails("http:?dangling-pct-%0");
diff --git a/test/core/compression/BUILD b/test/core/compression/BUILD
index a243a72029..9ddb4c52b4 100644
--- a/test/core/compression/BUILD
+++ b/test/core/compression/BUILD
@@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+licenses(["notice"]) # 3-clause BSD
+
cc_test(
name = "algorithm_test",
srcs = ["algorithm_test.c"],
diff --git a/test/core/end2end/BUILD b/test/core/end2end/BUILD
index a40fb8e083..0cef7aa01d 100644
--- a/test/core/end2end/BUILD
+++ b/test/core/end2end/BUILD
@@ -63,8 +63,8 @@ cc_library(
cc_library(
name = 'http_proxy',
- hdrs = ['fixtures/http_proxy.h'],
- srcs = ['fixtures/http_proxy.c'],
+ hdrs = ['fixtures/http_proxy_fixture.h'],
+ srcs = ['fixtures/http_proxy_fixture.c'],
copts = ['-std=c99'],
deps = ['//:gpr', '//:grpc', '//test/core/util:grpc_test_util']
)
diff --git a/test/core/end2end/end2end_tests.h b/test/core/end2end/end2end_tests.h
index cb0afd9cd9..cdb26a67e9 100644
--- a/test/core/end2end/end2end_tests.h
+++ b/test/core/end2end/end2end_tests.h
@@ -39,12 +39,15 @@
typedef struct grpc_end2end_test_fixture grpc_end2end_test_fixture;
typedef struct grpc_end2end_test_config grpc_end2end_test_config;
+/* Test feature flags. */
#define FEATURE_MASK_SUPPORTS_DELAYED_CONNECTION 1
#define FEATURE_MASK_SUPPORTS_HOSTNAME_VERIFICATION 2
#define FEATURE_MASK_SUPPORTS_PER_CALL_CREDENTIALS 4
#define FEATURE_MASK_SUPPORTS_REQUEST_PROXYING 8
#define FEATURE_MASK_SUPPORTS_CLIENT_CHANNEL 16
#define FEATURE_MASK_SUPPORTS_AUTHORITY_HEADER 32
+#define FEATURE_MASK_DOES_NOT_SUPPORT_RESOURCE_QUOTA_SERVER 64
+#define FEATURE_MASK_DOES_NOT_SUPPORT_NETWORK_STATUS_CHANGE 128
#define FAIL_AUTH_CHECK_SERVER_ARG_NAME "fail_auth_check"
@@ -56,8 +59,12 @@ struct grpc_end2end_test_fixture {
};
struct grpc_end2end_test_config {
+ /* A descriptive name for this test fixture. */
const char *name;
+
+ /* Which features are supported by this fixture. See feature flags above. */
uint32_t feature_mask;
+
grpc_end2end_test_fixture (*create_fixture)(grpc_channel_args *client_args,
grpc_channel_args *server_args);
void (*init_client)(grpc_end2end_test_fixture *f,
diff --git a/test/core/end2end/fixtures/h2_http_proxy.c b/test/core/end2end/fixtures/h2_http_proxy.c
index 44b223664a..55c65fa70e 100644
--- a/test/core/end2end/fixtures/h2_http_proxy.c
+++ b/test/core/end2end/fixtures/h2_http_proxy.c
@@ -49,7 +49,7 @@
#include "src/core/lib/support/env.h"
#include "src/core/lib/surface/channel.h"
#include "src/core/lib/surface/server.h"
-#include "test/core/end2end/fixtures/http_proxy.h"
+#include "test/core/end2end/fixtures/http_proxy_fixture.h"
#include "test/core/util/port.h"
#include "test/core/util/test_config.h"
diff --git a/test/core/end2end/fixtures/http_proxy.c b/test/core/end2end/fixtures/http_proxy_fixture.c
index 9ccb1263ee..bcd1c9914b 100644
--- a/test/core/end2end/fixtures/http_proxy.c
+++ b/test/core/end2end/fixtures/http_proxy_fixture.c
@@ -31,7 +31,7 @@
*
*/
-#include "test/core/end2end/fixtures/http_proxy.h"
+#include "test/core/end2end/fixtures/http_proxy_fixture.h"
#include "src/core/lib/iomgr/sockaddr.h"
diff --git a/test/core/end2end/fixtures/http_proxy.h b/test/core/end2end/fixtures/http_proxy_fixture.h
index cd47b432af..cd47b432af 100644
--- a/test/core/end2end/fixtures/http_proxy.h
+++ b/test/core/end2end/fixtures/http_proxy_fixture.h
diff --git a/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6520142139752448 b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6520142139752448
new file mode 100644
index 0000000000..49c02c2f12
--- /dev/null
+++ b/test/core/end2end/fuzzers/api_fuzzer_corpus/clusterfuzz-testcase-6520142139752448
Binary files differ
diff --git a/test/core/end2end/tests/filter_call_init_fails.c b/test/core/end2end/tests/filter_call_init_fails.c
index d2d6e82d57..65216cf19d 100644
--- a/test/core/end2end/tests/filter_call_init_fails.c
+++ b/test/core/end2end/tests/filter_call_init_fails.c
@@ -213,7 +213,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *and_free_memory) {}
+ grpc_closure *ignored) {}
static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
diff --git a/test/core/end2end/tests/filter_causes_close.c b/test/core/end2end/tests/filter_causes_close.c
index 25e606556d..c968f30b3b 100644
--- a/test/core/end2end/tests/filter_causes_close.c
+++ b/test/core/end2end/tests/filter_causes_close.c
@@ -236,7 +236,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
static void destroy_call_elem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *and_free_memory) {}
+ grpc_closure *ignored) {}
static grpc_error *init_channel_elem(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
diff --git a/test/core/end2end/tests/filter_latency.c b/test/core/end2end/tests/filter_latency.c
index d05e9e79a1..2428c92a42 100644
--- a/test/core/end2end/tests/filter_latency.c
+++ b/test/core/end2end/tests/filter_latency.c
@@ -267,7 +267,7 @@ static grpc_error *init_call_elem(grpc_exec_ctx *exec_ctx,
static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *and_free_memory) {
+ grpc_closure *ignored) {
gpr_mu_lock(&g_mu);
g_client_latency = final_info->stats.latency;
gpr_mu_unlock(&g_mu);
@@ -276,7 +276,7 @@ static void client_destroy_call_elem(grpc_exec_ctx *exec_ctx,
static void server_destroy_call_elem(grpc_exec_ctx *exec_ctx,
grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *and_free_memory) {
+ grpc_closure *ignored) {
gpr_mu_lock(&g_mu);
g_server_latency = final_info->stats.latency;
gpr_mu_unlock(&g_mu);
diff --git a/test/core/end2end/tests/network_status_change.c b/test/core/end2end/tests/network_status_change.c
index 7540ce93a1..d7a4106459 100644
--- a/test/core/end2end/tests/network_status_change.c
+++ b/test/core/end2end/tests/network_status_change.c
@@ -240,6 +240,10 @@ static void test_invoke_network_status_change(grpc_end2end_test_config config) {
}
void network_status_change(grpc_end2end_test_config config) {
+ if (config.feature_mask &
+ FEATURE_MASK_DOES_NOT_SUPPORT_NETWORK_STATUS_CHANGE) {
+ return;
+ }
test_invoke_network_status_change(config);
}
diff --git a/test/core/end2end/tests/resource_quota_server.c b/test/core/end2end/tests/resource_quota_server.c
index 4f9ed7a3a1..db26b4480e 100644
--- a/test/core/end2end/tests/resource_quota_server.c
+++ b/test/core/end2end/tests/resource_quota_server.c
@@ -113,6 +113,10 @@ static grpc_slice generate_random_slice() {
}
void resource_quota_server(grpc_end2end_test_config config) {
+ if (config.feature_mask &
+ FEATURE_MASK_DOES_NOT_SUPPORT_RESOURCE_QUOTA_SERVER) {
+ return;
+ }
grpc_resource_quota *resource_quota =
grpc_resource_quota_create("test_server");
grpc_resource_quota_resize(resource_quota, 5 * 1024 * 1024);
diff --git a/test/core/end2end/tests/streaming_error_response.c b/test/core/end2end/tests/streaming_error_response.c
index 42055907c8..2b9c404b15 100644
--- a/test/core/end2end/tests/streaming_error_response.c
+++ b/test/core/end2end/tests/streaming_error_response.c
@@ -31,6 +31,9 @@
*
*/
+/** \file Verify that status ordering rules are obeyed.
+ \ref doc/status_ordering.md */
+
#include "test/core/end2end/end2end_tests.h"
#include <stdio.h>
diff --git a/test/core/fling/fling_stream_test.c b/test/core/fling/fling_stream_test.c
index 7e4daaa84f..948659ab2f 100644
--- a/test/core/fling/fling_stream_test.c
+++ b/test/core/fling/fling_stream_test.c
@@ -31,22 +31,13 @@
*
*/
-#ifndef _POSIX_SOURCE
-#define _POSIX_SOURCE
-#endif
-
-#include <assert.h>
-#include <signal.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.h>
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/string_util.h>
+#include <grpc/support/subprocess.h>
#include "src/core/lib/support/string.h"
#include "test/core/util/port.h"
@@ -57,10 +48,7 @@ int main(int argc, char **argv) {
int port = grpc_pick_unused_port_or_die();
char *args[10];
int status;
- pid_t svr, cli;
- /* seed rng with pid, so we don't end up with the same random numbers as a
- concurrently running test binary */
- srand((unsigned)getpid());
+ gpr_subprocess *svr, *cli;
/* figure out where we are */
if (lslash) {
memcpy(root, me, (size_t)(lslash - me));
@@ -69,45 +57,38 @@ int main(int argc, char **argv) {
strcpy(root, ".");
}
/* start the server */
- svr = fork();
- if (svr == 0) {
- gpr_asprintf(&args[0], "%s/fling_server", root);
- args[1] = "--bind";
- gpr_join_host_port(&args[2], "::", port);
- args[3] = "--no-secure";
- args[4] = 0;
- execv(args[0], args);
+ gpr_asprintf(&args[0], "%s/fling_server%s", root,
+ gpr_subprocess_binary_extension());
+ args[1] = "--bind";
+ gpr_join_host_port(&args[2], "::", port);
+ args[3] = "--no-secure";
+ svr = gpr_subprocess_create(4, (const char **)args);
+ gpr_free(args[0]);
+ gpr_free(args[2]);
- gpr_free(args[0]);
- gpr_free(args[2]);
- return 1;
- }
- /* wait a little */
- sleep(2);
/* start the client */
- cli = fork();
- if (cli == 0) {
- gpr_asprintf(&args[0], "%s/fling_client", root);
- args[1] = "--target";
- gpr_join_host_port(&args[2], "127.0.0.1", port);
- args[3] = "--scenario=ping-pong-stream";
- args[4] = "--no-secure";
- args[5] = 0;
- execv(args[0], args);
+ gpr_asprintf(&args[0], "%s/fling_client%s", root,
+ gpr_subprocess_binary_extension());
+ args[1] = "--target";
+ gpr_join_host_port(&args[2], "127.0.0.1", port);
+ args[3] = "--scenario=ping-pong-stream";
+ args[4] = "--no-secure";
+ args[5] = 0;
+ cli = gpr_subprocess_create(6, (const char **)args);
+ gpr_free(args[0]);
+ gpr_free(args[2]);
- gpr_free(args[0]);
- gpr_free(args[2]);
- return 1;
- }
/* wait for completion */
printf("waiting for client\n");
- if (waitpid(cli, &status, 0) == -1) return 2;
- if (!WIFEXITED(status)) return 4;
- if (WEXITSTATUS(status)) return WEXITSTATUS(status);
- printf("waiting for server\n");
- kill(svr, SIGINT);
- if (waitpid(svr, &status, 0) == -1) return 2;
- if (!WIFEXITED(status)) return 4;
- if (WEXITSTATUS(status)) return WEXITSTATUS(status);
- return 0;
+ if ((status = gpr_subprocess_join(cli))) {
+ gpr_subprocess_destroy(cli);
+ gpr_subprocess_destroy(svr);
+ return status;
+ }
+ gpr_subprocess_destroy(cli);
+
+ gpr_subprocess_interrupt(svr);
+ status = gpr_subprocess_join(svr);
+ gpr_subprocess_destroy(svr);
+ return status;
}
diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD
index 864e0db00b..eb8f3a9beb 100644
--- a/test/core/handshake/BUILD
+++ b/test/core/handshake/BUILD
@@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+licenses(["notice"]) # 3-clause BSD
+
cc_test(
name = "client_ssl",
srcs = ["client_ssl.c"],
diff --git a/test/core/iomgr/error_test.c b/test/core/iomgr/error_test.c
new file mode 100644
index 0000000000..2a6b1b17fd
--- /dev/null
+++ b/test/core/iomgr/error_test.c
@@ -0,0 +1,219 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/core/lib/iomgr/error.h"
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/useful.h>
+
+#include <string.h>
+
+#include "test/core/util/test_config.h"
+
+static void test_set_get_int() {
+ grpc_error* error = GRPC_ERROR_CREATE("Test");
+ GPR_ASSERT(error);
+ intptr_t i = 0;
+ GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_FILE_LINE, &i));
+ GPR_ASSERT(i); // line set will never be 0
+ GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
+ GPR_ASSERT(!grpc_error_get_int(error, GRPC_ERROR_INT_SIZE, &i));
+
+ intptr_t errnumber = 314;
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_ERRNO, errnumber);
+ GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
+ GPR_ASSERT(i == errnumber);
+
+ intptr_t http = 2;
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_HTTP2_ERROR, http);
+ GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_HTTP2_ERROR, &i));
+ GPR_ASSERT(i == http);
+
+ GRPC_ERROR_UNREF(error);
+}
+
+static void test_set_get_str() {
+ grpc_error* error = GRPC_ERROR_CREATE("Test");
+
+ GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL));
+ GPR_ASSERT(!grpc_error_get_str(error, GRPC_ERROR_STR_TSI_ERROR));
+
+ const char* c = grpc_error_get_str(error, GRPC_ERROR_STR_FILE);
+ GPR_ASSERT(c);
+ GPR_ASSERT(strstr(c, "error_test.c")); // __FILE__ expands differently on
+ // Windows. All should at least
+ // contain error_test.c
+
+ c = grpc_error_get_str(error, GRPC_ERROR_STR_DESCRIPTION);
+ GPR_ASSERT(c);
+ GPR_ASSERT(!strcmp(c, "Test"));
+
+ error =
+ grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, "longer message");
+ c = grpc_error_get_str(error, GRPC_ERROR_STR_GRPC_MESSAGE);
+ GPR_ASSERT(c);
+ GPR_ASSERT(!strcmp(c, "longer message"));
+
+ GRPC_ERROR_UNREF(error);
+}
+
+static void test_copy_and_unref() {
+ // error1 has one ref
+ grpc_error* error1 = grpc_error_set_str(
+ GRPC_ERROR_CREATE("Test"), GRPC_ERROR_STR_GRPC_MESSAGE, "message");
+ const char* c = grpc_error_get_str(error1, GRPC_ERROR_STR_GRPC_MESSAGE);
+ GPR_ASSERT(c);
+ GPR_ASSERT(!strcmp(c, "message"));
+
+ // error 1 has two refs
+ GRPC_ERROR_REF(error1);
+ // this gives error3 a ref to the new error, and decrements error1 to one ref
+ grpc_error* error3 =
+ grpc_error_set_str(error1, GRPC_ERROR_STR_SYSCALL, "syscall");
+ GPR_ASSERT(error3 != error1); // should not be the same because of extra ref
+ c = grpc_error_get_str(error3, GRPC_ERROR_STR_GRPC_MESSAGE);
+ GPR_ASSERT(c);
+ GPR_ASSERT(!strcmp(c, "message"));
+
+ // error 1 should not have a syscall but 3 should
+ GPR_ASSERT(!grpc_error_get_str(error1, GRPC_ERROR_STR_SYSCALL));
+ c = grpc_error_get_str(error3, GRPC_ERROR_STR_SYSCALL);
+ GPR_ASSERT(c);
+ GPR_ASSERT(!strcmp(c, "syscall"));
+
+ GRPC_ERROR_UNREF(error1);
+ GRPC_ERROR_UNREF(error3);
+}
+
+static void test_create_referencing() {
+ grpc_error* child = grpc_error_set_str(
+ GRPC_ERROR_CREATE("Child"), GRPC_ERROR_STR_GRPC_MESSAGE, "message");
+ grpc_error* parent = GRPC_ERROR_CREATE_REFERENCING("Parent", &child, 1);
+ GPR_ASSERT(parent);
+
+ GRPC_ERROR_UNREF(child);
+ GRPC_ERROR_UNREF(parent);
+}
+
+static void test_create_referencing_many() {
+ grpc_error* children[3];
+ children[0] = grpc_error_set_str(GRPC_ERROR_CREATE("Child1"),
+ GRPC_ERROR_STR_GRPC_MESSAGE, "message");
+ children[1] = grpc_error_set_int(GRPC_ERROR_CREATE("Child2"),
+ GRPC_ERROR_INT_HTTP2_ERROR, 5);
+ children[2] = grpc_error_set_str(GRPC_ERROR_CREATE("Child3"),
+ GRPC_ERROR_STR_GRPC_MESSAGE, "message 3");
+
+ grpc_error* parent = GRPC_ERROR_CREATE_REFERENCING("Parent", children, 3);
+ GPR_ASSERT(parent);
+
+ for (size_t i = 0; i < 3; ++i) {
+ GRPC_ERROR_UNREF(children[i]);
+ }
+ GRPC_ERROR_UNREF(parent);
+}
+
+static void print_error_string() {
+ grpc_error* error =
+ grpc_error_set_int(GRPC_ERROR_CREATE("Error"), GRPC_ERROR_INT_GRPC_STATUS,
+ GRPC_STATUS_UNIMPLEMENTED);
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_SIZE, 666);
+ error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, "message");
+ // gpr_log(GPR_DEBUG, "%s", grpc_error_string(error));
+ GRPC_ERROR_UNREF(error);
+}
+
+static void print_error_string_reference() {
+ grpc_error* children[2];
+ children[0] = grpc_error_set_str(
+ grpc_error_set_int(GRPC_ERROR_CREATE("1"), GRPC_ERROR_INT_GRPC_STATUS,
+ GRPC_STATUS_UNIMPLEMENTED),
+ GRPC_ERROR_STR_GRPC_MESSAGE, "message for child 1");
+ children[1] = grpc_error_set_str(
+ grpc_error_set_int(GRPC_ERROR_CREATE("2sd"), GRPC_ERROR_INT_GRPC_STATUS,
+ GRPC_STATUS_INTERNAL),
+ GRPC_ERROR_STR_GRPC_MESSAGE, "message for child 2");
+
+ grpc_error* parent = GRPC_ERROR_CREATE_REFERENCING("Parent", children, 2);
+
+ gpr_log(GPR_DEBUG, "%s", grpc_error_string(parent));
+
+ for (size_t i = 0; i < 2; ++i) {
+ GRPC_ERROR_UNREF(children[i]);
+ }
+ GRPC_ERROR_UNREF(parent);
+}
+
+static void test_os_error() {
+ int fake_errno = 5;
+ const char* syscall = "syscall name";
+ grpc_error* error = GRPC_OS_ERROR(fake_errno, syscall);
+
+ intptr_t i = 0;
+ GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_ERRNO, &i));
+ GPR_ASSERT(i == fake_errno);
+
+ const char* c = grpc_error_get_str(error, GRPC_ERROR_STR_SYSCALL);
+ GPR_ASSERT(c);
+ GPR_ASSERT(!strcmp(c, syscall));
+ GRPC_ERROR_UNREF(error);
+}
+
+static void test_special() {
+ grpc_error* error = GRPC_ERROR_NONE;
+ error = grpc_error_add_child(error, GRPC_ERROR_CREATE("test child"));
+ intptr_t i;
+ GPR_ASSERT(grpc_error_get_int(error, GRPC_ERROR_INT_GRPC_STATUS, &i));
+ GPR_ASSERT(i == GRPC_STATUS_OK);
+ GRPC_ERROR_UNREF(error);
+}
+
+int main(int argc, char** argv) {
+ grpc_test_init(argc, argv);
+ grpc_init();
+ test_set_get_int();
+ test_set_get_str();
+ test_copy_and_unref();
+ print_error_string();
+ print_error_string_reference();
+ test_os_error();
+ test_create_referencing();
+ test_create_referencing_many();
+ test_special();
+ grpc_shutdown();
+
+ return 0;
+}
diff --git a/test/core/iomgr/sockaddr_utils_test.c b/test/core/iomgr/sockaddr_utils_test.c
index 8569c697fe..70a6c323e5 100644
--- a/test/core/iomgr/sockaddr_utils_test.c
+++ b/test/core/iomgr/sockaddr_utils_test.c
@@ -70,6 +70,12 @@ static grpc_resolved_address make_addr6(const uint8_t *data, size_t data_len) {
return resolved_addr6;
}
+static void set_addr6_scope_id(grpc_resolved_address *addr, uint32_t scope_id) {
+ struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr->addr;
+ GPR_ASSERT(addr6->sin6_family == AF_INET6);
+ addr6->sin6_scope_id = scope_id;
+}
+
static const uint8_t kMapped[] = {0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0xff, 0xff, 192, 0, 2, 1};
@@ -222,6 +228,16 @@ static void test_sockaddr_to_string(void) {
expect_sockaddr_str("[2001:db8::1]:12345", &input6, 1);
expect_sockaddr_uri("ipv6:[2001:db8::1]:12345", &input6);
+ set_addr6_scope_id(&input6, 2);
+ expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 0);
+ expect_sockaddr_str("[2001:db8::1%252]:12345", &input6, 1);
+ expect_sockaddr_uri("ipv6:[2001:db8::1%252]:12345", &input6);
+
+ set_addr6_scope_id(&input6, 101);
+ expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 0);
+ expect_sockaddr_str("[2001:db8::1%25101]:12345", &input6, 1);
+ expect_sockaddr_uri("ipv6:[2001:db8::1%25101]:12345", &input6);
+
input6 = make_addr6(kMapped, sizeof(kMapped));
expect_sockaddr_str("[::ffff:192.0.2.1]:12345", &input6, 0);
expect_sockaddr_str("192.0.2.1:12345", &input6, 1);
diff --git a/test/core/iomgr/tcp_client_uv_test.c b/test/core/iomgr/tcp_client_uv_test.c
index f8938d0abb..064119f11b 100644
--- a/test/core/iomgr/tcp_client_uv_test.c
+++ b/test/core/iomgr/tcp_client_uv_test.c
@@ -58,7 +58,7 @@ static int g_connections_complete = 0;
static grpc_endpoint *g_connecting = NULL;
static gpr_timespec test_deadline(void) {
- return GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
+ return grpc_timeout_seconds_to_deadline(10);
}
static void finish_connection() {
@@ -73,7 +73,8 @@ static void must_succeed(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
GPR_ASSERT(g_connecting != NULL);
GPR_ASSERT(error == GRPC_ERROR_NONE);
- grpc_endpoint_shutdown(exec_ctx, g_connecting);
+ grpc_endpoint_shutdown(exec_ctx, g_connecting,
+ GRPC_ERROR_CREATE("must_succeed called"));
grpc_endpoint_destroy(exec_ctx, g_connecting);
g_connecting = NULL;
finish_connection();
@@ -133,7 +134,7 @@ void test_succeeds(void) {
"pollset_work",
grpc_pollset_work(&exec_ctx, g_pollset, &worker,
gpr_now(GPR_CLOCK_MONOTONIC),
- GRPC_TIMEOUT_SECONDS_TO_DEADLINE(5))));
+ grpc_timeout_seconds_to_deadline(5))));
gpr_mu_unlock(g_mu);
grpc_exec_ctx_flush(&exec_ctx);
gpr_mu_lock(g_mu);
diff --git a/test/core/iomgr/tcp_server_posix_test.c b/test/core/iomgr/tcp_server_posix_test.c
index efadddc011..6e514324a5 100644
--- a/test/core/iomgr/tcp_server_posix_test.c
+++ b/test/core/iomgr/tcp_server_posix_test.c
@@ -454,7 +454,8 @@ int main(int argc, char **argv) {
const grpc_channel_args channel_args = {1, chan_args};
struct ifaddrs *ifa = NULL;
struct ifaddrs *ifa_it;
- test_addrs dst_addrs;
+ // Zalloc dst_addrs to avoid oversized frames.
+ test_addrs *dst_addrs = gpr_zalloc(sizeof(*dst_addrs));
grpc_test_init(argc, argv);
grpc_init();
g_pollset = gpr_zalloc(grpc_pollset_size());
@@ -469,24 +470,25 @@ int main(int argc, char **argv) {
gpr_log(GPR_ERROR, "getifaddrs: %s", strerror(errno));
return EXIT_FAILURE;
}
- dst_addrs.naddrs = 0;
- for (ifa_it = ifa; ifa_it != NULL && dst_addrs.naddrs < MAX_ADDRS;
+ dst_addrs->naddrs = 0;
+ for (ifa_it = ifa; ifa_it != NULL && dst_addrs->naddrs < MAX_ADDRS;
ifa_it = ifa_it->ifa_next) {
if (ifa_it->ifa_addr == NULL) {
continue;
} else if (ifa_it->ifa_addr->sa_family == AF_INET) {
- dst_addrs.addrs[dst_addrs.naddrs].addr.len = sizeof(struct sockaddr_in);
+ dst_addrs->addrs[dst_addrs->naddrs].addr.len = sizeof(struct sockaddr_in);
} else if (ifa_it->ifa_addr->sa_family == AF_INET6) {
- dst_addrs.addrs[dst_addrs.naddrs].addr.len = sizeof(struct sockaddr_in6);
+ dst_addrs->addrs[dst_addrs->naddrs].addr.len =
+ sizeof(struct sockaddr_in6);
} else {
continue;
}
- memcpy(dst_addrs.addrs[dst_addrs.naddrs].addr.addr, ifa_it->ifa_addr,
- dst_addrs.addrs[dst_addrs.naddrs].addr.len);
+ memcpy(dst_addrs->addrs[dst_addrs->naddrs].addr.addr, ifa_it->ifa_addr,
+ dst_addrs->addrs[dst_addrs->naddrs].addr.len);
GPR_ASSERT(
- grpc_sockaddr_set_port(&dst_addrs.addrs[dst_addrs.naddrs].addr, 0));
- test_addr_init_str(&dst_addrs.addrs[dst_addrs.naddrs]);
- ++dst_addrs.naddrs;
+ grpc_sockaddr_set_port(&dst_addrs->addrs[dst_addrs->naddrs].addr, 0));
+ test_addr_init_str(&dst_addrs->addrs[dst_addrs->naddrs]);
+ ++dst_addrs->naddrs;
}
freeifaddrs(ifa);
ifa = NULL;
@@ -495,20 +497,21 @@ int main(int argc, char **argv) {
test_connect(1, NULL, NULL, false);
test_connect(10, NULL, NULL, false);
- /* Set dst_addrs.addrs[i].len=0 for dst_addrs that are unreachable with a "::"
- listener. */
- test_connect(1, NULL, &dst_addrs, true);
+ /* Set dst_addrs->addrs[i].len=0 for dst_addrs that are unreachable with a
+ "::" listener. */
+ test_connect(1, NULL, dst_addrs, true);
/* Test connect(2) with dst_addrs. */
- test_connect(1, &channel_args, &dst_addrs, false);
+ test_connect(1, &channel_args, dst_addrs, false);
/* Test connect(2) with dst_addrs. */
- test_connect(10, &channel_args, &dst_addrs, false);
+ test_connect(10, &channel_args, dst_addrs, false);
grpc_closure_init(&destroyed, destroy_pollset, g_pollset,
grpc_schedule_on_exec_ctx);
grpc_pollset_shutdown(&exec_ctx, g_pollset, &destroyed);
grpc_exec_ctx_finish(&exec_ctx);
grpc_shutdown();
+ gpr_free(dst_addrs);
gpr_free(g_pollset);
return EXIT_SUCCESS;
}
diff --git a/test/core/iomgr/tcp_server_uv_test.c b/test/core/iomgr/tcp_server_uv_test.c
index 7b458c90f3..0fc74599ea 100644
--- a/test/core/iomgr/tcp_server_uv_test.c
+++ b/test/core/iomgr/tcp_server_uv_test.c
@@ -115,7 +115,7 @@ static void server_weak_ref_set(server_weak_ref *weak_ref,
static void on_connect(grpc_exec_ctx *exec_ctx, void *arg, grpc_endpoint *tcp,
grpc_pollset *pollset,
grpc_tcp_server_acceptor *acceptor) {
- grpc_endpoint_shutdown(exec_ctx, tcp);
+ grpc_endpoint_shutdown(exec_ctx, tcp, GRPC_ERROR_CREATE("Connected"));
grpc_endpoint_destroy(exec_ctx, tcp);
on_connect_result temp_result;
@@ -203,7 +203,7 @@ static void close_cb(uv_handle_t *handle) { gpr_free(handle); }
static void tcp_connect(grpc_exec_ctx *exec_ctx, const struct sockaddr *remote,
socklen_t remote_len, on_connect_result *result) {
- gpr_timespec deadline = GRPC_TIMEOUT_SECONDS_TO_DEADLINE(10);
+ gpr_timespec deadline = grpc_timeout_seconds_to_deadline(10);
uv_tcp_t *client_handle = gpr_malloc(sizeof(uv_tcp_t));
uv_connect_t *req = gpr_malloc(sizeof(uv_connect_t));
int nconnects_before;
diff --git a/test/core/iomgr/udp_server_test.c b/test/core/iomgr/udp_server_test.c
index d57a37b2a9..396ec959cd 100644
--- a/test/core/iomgr/udp_server_test.c
+++ b/test/core/iomgr/udp_server_test.c
@@ -62,8 +62,7 @@ static int g_number_of_writes = 0;
static int g_number_of_bytes_read = 0;
static int g_number_of_orphan_calls = 0;
-static void on_read(grpc_exec_ctx *exec_ctx, grpc_fd *emfd,
- grpc_server *server) {
+static void on_read(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, void *user_data) {
char read_buffer[512];
ssize_t byte_count;
@@ -79,7 +78,7 @@ static void on_read(grpc_exec_ctx *exec_ctx, grpc_fd *emfd,
gpr_mu_unlock(g_mu);
}
-static void on_write(grpc_exec_ctx *exec_ctx, grpc_fd *emfd) {
+static void on_write(grpc_exec_ctx *exec_ctx, grpc_fd *emfd, void *user_data) {
gpr_mu_lock(g_mu);
g_number_of_writes++;
@@ -88,7 +87,8 @@ static void on_write(grpc_exec_ctx *exec_ctx, grpc_fd *emfd) {
gpr_mu_unlock(g_mu);
}
-static void on_fd_orphaned(grpc_exec_ctx *exec_ctx, grpc_fd *emfd) {
+static void on_fd_orphaned(grpc_exec_ctx *exec_ctx, grpc_fd *emfd,
+ void *user_data) {
gpr_log(GPR_INFO, "gRPC FD about to be orphaned: %d",
grpc_fd_wrapped_fd(emfd));
g_number_of_orphan_calls++;
diff --git a/test/core/memory_usage/client.c b/test/core/memory_usage/client.c
index 09f0e2d867..107abbc1b3 100644
--- a/test/core/memory_usage/client.c
+++ b/test/core/memory_usage/client.c
@@ -43,6 +43,7 @@
#include <grpc/support/log.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
+#include "src/core/lib/support/env.h"
#include "src/core/lib/support/string.h"
#include "test/core/util/memory_counters.h"
#include "test/core/util/test_config.h"
@@ -310,6 +311,29 @@ int main(int argc, char **argv) {
server_calls_end.total_size_relative -
after_server_create.total_size_relative);
+ const char *csv_file = "memory_usage.csv";
+ FILE *csv = fopen(csv_file, "w");
+ if (csv) {
+ char *env_build = gpr_getenv("BUILD_NUMBER");
+ char *env_job = gpr_getenv("JOB_NAME");
+ fprintf(csv, "%f,%zi,%zi,%f,%zi,%s,%s\n",
+ (double)(client_calls_inflight.total_size_relative -
+ client_benchmark_calls_start.total_size_relative) /
+ benchmark_iterations,
+ client_channel_end.total_size_relative -
+ client_channel_start.total_size_relative,
+ after_server_create.total_size_relative -
+ before_server_create.total_size_relative,
+ (double)(server_calls_inflight.total_size_relative -
+ server_benchmark_calls_start.total_size_relative) /
+ benchmark_iterations,
+ server_calls_end.total_size_relative -
+ after_server_create.total_size_relative,
+ env_build == NULL ? "" : env_build, env_job == NULL ? "" : env_job);
+ fclose(csv);
+ gpr_log(GPR_INFO, "Summary written to %s", csv_file);
+ }
+
grpc_memory_counters_destroy();
return 0;
}
diff --git a/test/core/security/BUILD b/test/core/security/BUILD
index e750c39b7c..1cb03c5cfe 100644
--- a/test/core/security/BUILD
+++ b/test/core/security/BUILD
@@ -34,7 +34,7 @@ load("//test/core/util:grpc_fuzzer.bzl", "grpc_fuzzer")
grpc_fuzzer(
name = "ssl_server_fuzzer",
srcs = ["ssl_server_fuzzer.c"],
- deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util"],
+ deps = ["//:gpr", "//:grpc", "//test/core/util:grpc_test_util", "//test/core/end2end:ssl_test_data"],
corpus = "corpus",
copts = ["-std=c99"],
)
diff --git a/test/core/security/ssl_server_fuzzer.c b/test/core/security/ssl_server_fuzzer.c
index f789278add..7a3612c419 100644
--- a/test/core/security/ssl_server_fuzzer.c
+++ b/test/core/security/ssl_server_fuzzer.c
@@ -38,6 +38,7 @@
#include "src/core/lib/iomgr/load_file.h"
#include "src/core/lib/security/credentials/credentials.h"
#include "src/core/lib/security/transport/security_connector.h"
+#include "test/core/end2end/data/ssl_test_data.h"
#include "test/core/util/memory_counters.h"
#include "test/core/util/mock_endpoint.h"
@@ -46,10 +47,6 @@ bool squelch = true;
// Turning this on will fail the leak check.
bool leak_check = false;
-#define SSL_CERT_PATH "src/core/lib/tsi/test_creds/server1.pem"
-#define SSL_KEY_PATH "src/core/lib/tsi/test_creds/server1.key"
-#define SSL_CA_PATH "src/core/lib/tsi/test_creds/ca.pem"
-
static void discard_write(grpc_slice slice) {}
static void dont_log(gpr_log_func_args *args) {}
@@ -88,12 +85,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
// Load key pair and establish server SSL credentials.
grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
grpc_slice ca_slice, cert_slice, key_slice;
- GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
- grpc_load_file(SSL_CA_PATH, 1, &ca_slice)));
- GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
- grpc_load_file(SSL_CERT_PATH, 1, &cert_slice)));
- GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file",
- grpc_load_file(SSL_KEY_PATH, 1, &key_slice)));
+ ca_slice = grpc_slice_from_static_string(test_root_cert);
+ cert_slice = grpc_slice_from_static_string(test_server1_cert);
+ key_slice = grpc_slice_from_static_string(test_server1_key);
const char *ca_cert = (const char *)GRPC_SLICE_START_PTR(ca_slice);
pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice);
pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice);
diff --git a/test/core/slice/percent_encoding_test.c b/test/core/slice/percent_encoding_test.c
index 222e695fd4..89f8154955 100644
--- a/test/core/slice/percent_encoding_test.c
+++ b/test/core/slice/percent_encoding_test.c
@@ -146,6 +146,7 @@ int main(int argc, char **argv) {
TEST_VECTOR("\x0f", "%0F", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("\xff", "%FF", grpc_url_percent_encoding_unreserved_bytes);
TEST_VECTOR("\xee", "%EE", grpc_url_percent_encoding_unreserved_bytes);
+ TEST_VECTOR("%2", "%252", grpc_url_percent_encoding_unreserved_bytes);
TEST_NONCONFORMANT_VECTOR("%", "%",
grpc_url_percent_encoding_unreserved_bytes);
TEST_NONCONFORMANT_VECTOR("%A", "%A",
diff --git a/test/core/support/BUILD b/test/core/support/BUILD
index 08cee1441b..3183510db9 100644
--- a/test/core/support/BUILD
+++ b/test/core/support/BUILD
@@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+licenses(["notice"]) # 3-clause BSD
+
cc_test(
name = "alloc_test",
srcs = ["alloc_test.c"],
diff --git a/test/core/support/arena_test.c b/test/core/support/arena_test.c
new file mode 100644
index 0000000000..35b2bbd1b1
--- /dev/null
+++ b/test/core/support/arena_test.c
@@ -0,0 +1,139 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/core/lib/support/arena.h"
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/thd.h>
+#include <grpc/support/useful.h>
+#include <inttypes.h>
+#include <string.h>
+
+#include "src/core/lib/support/string.h"
+#include "test/core/util/test_config.h"
+
+static void test_noop(void) { gpr_arena_destroy(gpr_arena_create(1)); }
+
+static void test(const char *name, size_t init_size, const size_t *allocs,
+ size_t nallocs) {
+ gpr_strvec v;
+ char *s;
+ gpr_strvec_init(&v);
+ gpr_asprintf(&s, "test '%s': %" PRIdPTR " <- {", name, init_size);
+ gpr_strvec_add(&v, s);
+ for (size_t i = 0; i < nallocs; i++) {
+ gpr_asprintf(&s, "%" PRIdPTR ",", allocs[i]);
+ gpr_strvec_add(&v, s);
+ }
+ gpr_strvec_add(&v, gpr_strdup("}"));
+ s = gpr_strvec_flatten(&v, NULL);
+ gpr_strvec_destroy(&v);
+ gpr_log(GPR_INFO, "%s", s);
+ gpr_free(s);
+
+ gpr_arena *a = gpr_arena_create(init_size);
+ void **ps = gpr_zalloc(sizeof(*ps) * nallocs);
+ for (size_t i = 0; i < nallocs; i++) {
+ ps[i] = gpr_arena_alloc(a, allocs[i]);
+ // ensure no duplicate results
+ for (size_t j = 0; j < i; j++) {
+ GPR_ASSERT(ps[i] != ps[j]);
+ }
+ // ensure writable
+ memset(ps[i], 1, allocs[i]);
+ }
+ gpr_arena_destroy(a);
+ gpr_free(ps);
+}
+
+#define TEST(name, init_size, ...) \
+ static const size_t allocs_##name[] = {__VA_ARGS__}; \
+ test(#name, init_size, allocs_##name, GPR_ARRAY_SIZE(allocs_##name))
+
+#define CONCURRENT_TEST_ITERATIONS 100000
+#define CONCURRENT_TEST_THREADS 100
+
+typedef struct {
+ gpr_event ev_start;
+ gpr_arena *arena;
+} concurrent_test_args;
+
+static void concurrent_test_body(void *arg) {
+ concurrent_test_args *a = arg;
+ gpr_event_wait(&a->ev_start, gpr_inf_future(GPR_CLOCK_REALTIME));
+ for (size_t i = 0; i < CONCURRENT_TEST_ITERATIONS; i++) {
+ *(char *)gpr_arena_alloc(a->arena, 1) = (char)i;
+ }
+}
+
+static void concurrent_test(void) {
+ gpr_log(GPR_DEBUG, "concurrent_test");
+
+ concurrent_test_args args;
+ gpr_event_init(&args.ev_start);
+ args.arena = gpr_arena_create(1024);
+
+ gpr_thd_id thds[CONCURRENT_TEST_THREADS];
+
+ for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
+ gpr_thd_options opt = gpr_thd_options_default();
+ gpr_thd_options_set_joinable(&opt);
+ gpr_thd_new(&thds[i], concurrent_test_body, &args, &opt);
+ }
+
+ gpr_event_set(&args.ev_start, (void *)1);
+
+ for (int i = 0; i < CONCURRENT_TEST_THREADS; i++) {
+ gpr_thd_join(thds[i]);
+ }
+
+ gpr_arena_destroy(args.arena);
+}
+
+int main(int argc, char *argv[]) {
+ grpc_test_init(argc, argv);
+
+ test_noop();
+ TEST(0_1, 0, 1);
+ TEST(1_1, 1, 1);
+ TEST(1_2, 1, 2);
+ TEST(1_3, 1, 3);
+ TEST(1_inc, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
+ TEST(6_123, 6, 1, 2, 3);
+ concurrent_test();
+
+ return 0;
+}
diff --git a/test/core/support/cpu_test.c b/test/core/support/cpu_test.c
index ca0fe0ccb5..7b9bf6c5e1 100644
--- a/test/core/support/cpu_test.c
+++ b/test/core/support/cpu_test.c
@@ -81,9 +81,12 @@ static void worker_thread(void *arg) {
uint32_t cpu;
unsigned r = 12345678;
unsigned i, j;
- for (i = 0; i < 1000 / grpc_test_slowdown_factor(); i++) {
+ /* Avoid repetitive division calculations */
+ int64_t max_i = 1000 / grpc_test_slowdown_factor();
+ int64_t max_j = 1000000 / grpc_test_slowdown_factor();
+ for (i = 0; i < max_i; i++) {
/* run for a bit - just calculate something random. */
- for (j = 0; j < 1000000 / grpc_test_slowdown_factor(); j++) {
+ for (j = 0; j < max_j; j++) {
r = (r * 17) & ((r - i) | (r * i));
}
cpu = gpr_cpu_current_cpu();
diff --git a/test/core/surface/BUILD b/test/core/surface/BUILD
index c158413122..3d5e26ced3 100644
--- a/test/core/surface/BUILD
+++ b/test/core/surface/BUILD
@@ -27,6 +27,8 @@
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+licenses(["notice"]) # 3-clause BSD
+
cc_test(
name = "alarm_test",
srcs = ["alarm_test.c"],
diff --git a/test/core/transport/BUILD b/test/core/transport/BUILD
index 865b0c26ef..08b2fd3332 100644
--- a/test/core/transport/BUILD
+++ b/test/core/transport/BUILD
@@ -65,6 +65,13 @@ cc_test(
)
cc_test(
+ name = "stream_owned_slice_test",
+ srcs = ["stream_owned_slice_test.c"],
+ deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
+ copts = ['-std=c99']
+)
+
+cc_test(
name = "timeout_encoding_test",
srcs = ["timeout_encoding_test.c"],
deps = ["//:grpc", "//test/core/util:grpc_test_util", "//:gpr", "//test/core/util:gpr_test_util"],
diff --git a/test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112 b/test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112
new file mode 100644
index 0000000000..04d48d6d76
--- /dev/null
+++ b/test/core/transport/chttp2/hpack_parser_corpus/clusterfuzz-testcase-5298216461402112
Binary files differ
diff --git a/test/core/transport/stream_owned_slice_test.c b/test/core/transport/stream_owned_slice_test.c
new file mode 100644
index 0000000000..97ba1083f3
--- /dev/null
+++ b/test/core/transport/stream_owned_slice_test.c
@@ -0,0 +1,58 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/core/lib/transport/transport.h"
+
+#include "test/core/util/test_config.h"
+
+#include <grpc/support/log.h>
+
+static void do_nothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
+
+int main(int argc, char **argv) {
+ grpc_test_init(argc, argv);
+
+ uint8_t buffer[] = "abc123";
+ grpc_stream_refcount r;
+ GRPC_STREAM_REF_INIT(&r, 1, do_nothing, NULL, "test");
+ GPR_ASSERT(r.refs.count == 1);
+ grpc_slice slice =
+ grpc_slice_from_stream_owned_buffer(&r, buffer, sizeof(buffer));
+ GPR_ASSERT(GRPC_SLICE_START_PTR(slice) == buffer);
+ GPR_ASSERT(GRPC_SLICE_LENGTH(slice) == sizeof(buffer));
+ GPR_ASSERT(r.refs.count == 2);
+ grpc_slice_unref(slice);
+ GPR_ASSERT(r.refs.count == 1);
+
+ return 0;
+}
diff --git a/test/core/util/memory_counters.c b/test/core/util/memory_counters.c
index 7c8b620f34..c27065f260 100644
--- a/test/core/util/memory_counters.c
+++ b/test/core/util/memory_counters.c
@@ -46,17 +46,23 @@ static void *guard_malloc(size_t size);
static void *guard_realloc(void *vptr, size_t size);
static void guard_free(void *vptr);
+#ifdef GPR_LOW_LEVEL_COUNTERS
+/* hide these from the microbenchmark atomic stats */
+#define NO_BARRIER_FETCH_ADD(x, sz) \
+ __atomic_fetch_add((x), (sz), __ATOMIC_RELAXED)
+#define NO_BARRIER_LOAD(x) __atomic_load_n((x), __ATOMIC_RELAXED)
+#else
+#define NO_BARRIER_FETCH_ADD(x, sz) gpr_atm_no_barrier_fetch_add(x, sz)
+#define NO_BARRIER_LOAD(x) gpr_atm_no_barrier_load(x)
+#endif
+
static void *guard_malloc(size_t size) {
size_t *ptr;
if (!size) return NULL;
- gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_absolute,
- (gpr_atm)size);
- gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_relative,
- (gpr_atm)size);
- gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_allocs_absolute,
- (gpr_atm)1);
- gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_allocs_relative,
- (gpr_atm)1);
+ NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_absolute, (gpr_atm)size);
+ NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, (gpr_atm)size);
+ NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_absolute, (gpr_atm)1);
+ NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_relative, (gpr_atm)1);
ptr = g_old_allocs.malloc_fn(size + sizeof(size));
*ptr++ = size;
return ptr;
@@ -72,14 +78,10 @@ static void *guard_realloc(void *vptr, size_t size) {
return NULL;
}
--ptr;
- gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_absolute,
- (gpr_atm)size);
- gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_relative,
- -(gpr_atm)*ptr);
- gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_relative,
- (gpr_atm)size);
- gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_allocs_absolute,
- (gpr_atm)1);
+ NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_absolute, (gpr_atm)size);
+ NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, -(gpr_atm)*ptr);
+ NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, (gpr_atm)size);
+ NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_absolute, (gpr_atm)1);
ptr = g_old_allocs.realloc_fn(ptr, size + sizeof(size));
*ptr++ = size;
return ptr;
@@ -89,10 +91,8 @@ static void guard_free(void *vptr) {
size_t *ptr = vptr;
if (!vptr) return;
--ptr;
- gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_size_relative,
- -(gpr_atm)*ptr);
- gpr_atm_no_barrier_fetch_add(&g_memory_counters.total_allocs_relative,
- -(gpr_atm)1);
+ NO_BARRIER_FETCH_ADD(&g_memory_counters.total_size_relative, -(gpr_atm)*ptr);
+ NO_BARRIER_FETCH_ADD(&g_memory_counters.total_allocs_relative, -(gpr_atm)1);
g_old_allocs.free_fn(ptr);
}
@@ -112,12 +112,12 @@ void grpc_memory_counters_destroy() {
struct grpc_memory_counters grpc_memory_counters_snapshot() {
struct grpc_memory_counters counters;
counters.total_size_relative =
- gpr_atm_no_barrier_load(&g_memory_counters.total_size_relative);
+ NO_BARRIER_LOAD(&g_memory_counters.total_size_relative);
counters.total_size_absolute =
- gpr_atm_no_barrier_load(&g_memory_counters.total_size_absolute);
+ NO_BARRIER_LOAD(&g_memory_counters.total_size_absolute);
counters.total_allocs_relative =
- gpr_atm_no_barrier_load(&g_memory_counters.total_allocs_relative);
+ NO_BARRIER_LOAD(&g_memory_counters.total_allocs_relative);
counters.total_allocs_absolute =
- gpr_atm_no_barrier_load(&g_memory_counters.total_allocs_absolute);
+ NO_BARRIER_LOAD(&g_memory_counters.total_allocs_absolute);
return counters;
}
diff --git a/test/core/util/port_server_client.c b/test/core/util/port_server_client.c
index a851d01635..38054dd1e7 100644
--- a/test/core/util/port_server_client.c
+++ b/test/core/util/port_server_client.c
@@ -162,6 +162,15 @@ static void got_port_from_server(grpc_exec_ctx *exec_ctx, void *arg,
if (failed) {
grpc_httpcli_request req;
memset(&req, 0, sizeof(req));
+ if (pr->retries >= 5) {
+ gpr_mu_lock(pr->mu);
+ pr->port = 0;
+ GRPC_LOG_IF_ERROR(
+ "pollset_kick",
+ grpc_pollset_kick(grpc_polling_entity_pollset(&pr->pops), NULL));
+ gpr_mu_unlock(pr->mu);
+ return;
+ }
GPR_ASSERT(pr->retries < 10);
gpr_sleep_until(gpr_time_add(
gpr_now(GPR_CLOCK_REALTIME),
diff --git a/test/core/util/trickle_endpoint.c b/test/core/util/trickle_endpoint.c
index 7ab0488a66..0848147158 100644
--- a/test/core/util/trickle_endpoint.c
+++ b/test/core/util/trickle_endpoint.c
@@ -31,6 +31,8 @@
*
*/
+#include "src/core/lib/iomgr/sockaddr.h"
+
#include "test/core/util/passthru_endpoint.h"
#include <inttypes.h>
@@ -40,9 +42,6 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/useful.h>
-
-#include "src/core/lib/iomgr/sockaddr.h"
-
#include "src/core/lib/slice/slice_internal.h"
typedef struct {
diff --git a/test/cpp/codegen/compiler_test_golden b/test/cpp/codegen/compiler_test_golden
index 0b82f2a59f..fd26a17ac1 100644
--- a/test/cpp/codegen/compiler_test_golden
+++ b/test/cpp/codegen/compiler_test_golden
@@ -1,4 +1,4 @@
-// Generated by the gRPC protobuf plugin.
+// Generated by the gRPC C++ plugin.
// If you make any local change, they will be lost.
// source: src/proto/grpc/testing/compiler_test.proto
// Original file comments:
diff --git a/test/cpp/common/channel_arguments_test.cc b/test/cpp/common/channel_arguments_test.cc
index 190d32ce06..9bcc9f99f6 100644
--- a/test/cpp/common/channel_arguments_test.cc
+++ b/test/cpp/common/channel_arguments_test.cc
@@ -230,13 +230,6 @@ TEST_F(ChannelArgumentsTest, SetSocketMutator) {
EXPECT_TRUE(HasArg(arg1));
// arg0 is replaced by arg1
EXPECT_FALSE(HasArg(arg0));
-
- // arg0 is destroyed by grpc_socket_mutator_to_arg(mutator1)
- {
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- arg1.value.pointer.vtable->destroy(&exec_ctx, arg1.value.pointer.p);
- grpc_exec_ctx_finish(&exec_ctx);
- }
}
TEST_F(ChannelArgumentsTest, SetUserAgentPrefix) {
diff --git a/test/cpp/interop/http2_client.cc b/test/cpp/interop/http2_client.cc
index 01c07823cf..38a437f39f 100644
--- a/test/cpp/interop/http2_client.cc
+++ b/test/cpp/interop/http2_client.cc
@@ -41,7 +41,7 @@
#include <grpc/support/useful.h>
#include "src/core/lib/transport/byte_stream.h"
-#include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/cpp/interop/http2_client.h"
diff --git a/test/cpp/interop/http2_client.h b/test/cpp/interop/http2_client.h
index 12df5d26bc..e57d695205 100644
--- a/test/cpp/interop/http2_client.h
+++ b/test/cpp/interop/http2_client.h
@@ -38,7 +38,7 @@
#include <grpc++/channel.h>
#include <grpc/grpc.h>
-#include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
namespace grpc {
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index b7f2723c39..55ba324cc7 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -46,8 +46,8 @@
#include <grpc/support/useful.h>
#include "src/core/lib/transport/byte_stream.h"
-#include "src/proto/grpc/testing/empty.grpc.pb.h"
-#include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/empty.pb.h"
+#include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/cpp/interop/client_helper.h"
#include "test/cpp/interop/interop_client.h"
diff --git a/test/cpp/interop/interop_client.h b/test/cpp/interop/interop_client.h
index 74f4db6b78..efcb7d2860 100644
--- a/test/cpp/interop/interop_client.h
+++ b/test/cpp/interop/interop_client.h
@@ -38,7 +38,7 @@
#include <grpc++/channel.h>
#include <grpc/grpc.h>
-#include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
namespace grpc {
diff --git a/test/cpp/interop/interop_server.cc b/test/cpp/interop/interop_server.cc
index 5a810b45ef..1cbca17928 100644
--- a/test/cpp/interop/interop_server.cc
+++ b/test/cpp/interop/interop_server.cc
@@ -48,8 +48,8 @@
#include "src/core/lib/support/string.h"
#include "src/core/lib/transport/byte_stream.h"
-#include "src/proto/grpc/testing/empty.grpc.pb.h"
-#include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/empty.pb.h"
+#include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/cpp/interop/server_helper.h"
#include "test/cpp/util/test_config.h"
diff --git a/test/cpp/interop/reconnect_interop_client.cc b/test/cpp/interop/reconnect_interop_client.cc
index 1c2f606637..01d985068d 100644
--- a/test/cpp/interop/reconnect_interop_client.cc
+++ b/test/cpp/interop/reconnect_interop_client.cc
@@ -40,8 +40,8 @@
#include <grpc++/support/channel_arguments.h>
#include <grpc/grpc.h>
#include <grpc/support/log.h>
-#include "src/proto/grpc/testing/empty.grpc.pb.h"
-#include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/empty.pb.h"
+#include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/cpp/util/create_test_channel.h"
#include "test/cpp/util/test_config.h"
diff --git a/test/cpp/interop/reconnect_interop_server.cc b/test/cpp/interop/reconnect_interop_server.cc
index 634d0a90fc..8d1b884af9 100644
--- a/test/cpp/interop/reconnect_interop_server.cc
+++ b/test/cpp/interop/reconnect_interop_server.cc
@@ -47,8 +47,8 @@
#include <grpc/grpc.h>
#include <grpc/support/log.h>
-#include "src/proto/grpc/testing/empty.grpc.pb.h"
-#include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/empty.pb.h"
+#include "src/proto/grpc/testing/messages.pb.h"
#include "src/proto/grpc/testing/test.grpc.pb.h"
#include "test/core/util/reconnect_server.h"
#include "test/cpp/util/test_config.h"
diff --git a/test/cpp/microbenchmarks/bm_arena.cc b/test/cpp/microbenchmarks/bm_arena.cc
new file mode 100644
index 0000000000..770c0b6d47
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_arena.cc
@@ -0,0 +1,76 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Benchmark arenas */
+
+extern "C" {
+#include "src/core/lib/support/arena.h"
+}
+#include "test/cpp/microbenchmarks/helpers.h"
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+static void BM_Arena_NoOp(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ gpr_arena_destroy(gpr_arena_create(state.range(0)));
+ }
+}
+BENCHMARK(BM_Arena_NoOp)->Range(1, 1024 * 1024);
+
+static void BM_Arena_ManyAlloc(benchmark::State& state) {
+ gpr_arena* a = gpr_arena_create(state.range(0));
+ const size_t realloc_after =
+ 1024 * 1024 * 1024 / ((state.range(1) + 15) & 0xffffff0u);
+ while (state.KeepRunning()) {
+ gpr_arena_alloc(a, state.range(1));
+ // periodically recreate arena to avoid OOM
+ if (state.iterations() % realloc_after == 0) {
+ gpr_arena_destroy(a);
+ a = gpr_arena_create(state.range(0));
+ }
+ }
+ gpr_arena_destroy(a);
+}
+BENCHMARK(BM_Arena_ManyAlloc)->Ranges({{1, 1024 * 1024}, {1, 32 * 1024}});
+
+static void BM_Arena_Batch(benchmark::State& state) {
+ while (state.KeepRunning()) {
+ gpr_arena* a = gpr_arena_create(state.range(0));
+ for (int i = 0; i < state.range(1); i++) {
+ gpr_arena_alloc(a, state.range(2));
+ }
+ gpr_arena_destroy(a);
+ }
+}
+BENCHMARK(BM_Arena_Batch)->Ranges({{1, 64 * 1024}, {1, 64}, {1, 1024}});
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_call_create.cc b/test/cpp/microbenchmarks/bm_call_create.cc
index 76d5030276..5ef40abb97 100644
--- a/test/cpp/microbenchmarks/bm_call_create.cc
+++ b/test/cpp/microbenchmarks/bm_call_create.cc
@@ -37,6 +37,7 @@
#include <string.h>
#include <sstream>
+#include <grpc++/channel.h>
#include <grpc++/support/channel_arguments.h>
#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
@@ -55,28 +56,106 @@ extern "C" {
#include "src/core/lib/transport/transport_impl.h"
}
+#include "src/cpp/client/create_channel_internal.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/cpp/microbenchmarks/helpers.h"
#include "third_party/benchmark/include/benchmark/benchmark.h"
-static struct Init {
- Init() { grpc_init(); }
- ~Init() { grpc_shutdown(); }
-} g_init;
+auto &force_library_initialization = Library::get();
-static void BM_InsecureChannelWithDefaults(benchmark::State &state) {
- grpc_channel *channel =
- grpc_insecure_channel_create("localhost:12345", NULL, NULL);
+void BM_Zalloc(benchmark::State &state) {
+ // speed of light for call creation is zalloc, so benchmark a few interesting
+ // sizes
+ size_t sz = state.range(0);
+ while (state.KeepRunning()) {
+ gpr_free(gpr_zalloc(sz));
+ }
+}
+BENCHMARK(BM_Zalloc)
+ ->Arg(64)
+ ->Arg(128)
+ ->Arg(256)
+ ->Arg(512)
+ ->Arg(1024)
+ ->Arg(1536)
+ ->Arg(2048)
+ ->Arg(3072)
+ ->Arg(4096)
+ ->Arg(5120)
+ ->Arg(6144)
+ ->Arg(7168);
+
+class BaseChannelFixture {
+ public:
+ BaseChannelFixture(grpc_channel *channel) : channel_(channel) {}
+ ~BaseChannelFixture() { grpc_channel_destroy(channel_); }
+
+ grpc_channel *channel() const { return channel_; }
+
+ private:
+ grpc_channel *const channel_;
+};
+
+class InsecureChannel : public BaseChannelFixture {
+ public:
+ InsecureChannel()
+ : BaseChannelFixture(
+ grpc_insecure_channel_create("localhost:1234", NULL, NULL)) {}
+};
+
+class LameChannel : public BaseChannelFixture {
+ public:
+ LameChannel()
+ : BaseChannelFixture(grpc_lame_client_channel_create(
+ "localhost:1234", GRPC_STATUS_UNAUTHENTICATED, "blah")) {}
+};
+
+template <class Fixture>
+static void BM_CallCreateDestroy(benchmark::State &state) {
+ TrackCounters track_counters;
+ Fixture fixture;
grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
- grpc_slice method = grpc_slice_from_static_string("/foo/bar");
gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+ void *method_hdl =
+ grpc_channel_register_call(fixture.channel(), "/foo/bar", NULL, NULL);
while (state.KeepRunning()) {
- grpc_call_destroy(grpc_channel_create_call(channel, NULL,
- GRPC_PROPAGATE_DEFAULTS, cq,
- method, NULL, deadline, NULL));
+ grpc_call_destroy(grpc_channel_create_registered_call(
+ fixture.channel(), NULL, GRPC_PROPAGATE_DEFAULTS, cq, method_hdl,
+ deadline, NULL));
}
- grpc_channel_destroy(channel);
grpc_completion_queue_destroy(cq);
+ track_counters.Finish(state);
+}
+
+BENCHMARK_TEMPLATE(BM_CallCreateDestroy, InsecureChannel);
+BENCHMARK_TEMPLATE(BM_CallCreateDestroy, LameChannel);
+
+static void *tag(int i) {
+ return reinterpret_cast<void *>(static_cast<intptr_t>(i));
+}
+
+static void BM_LameChannelCallCreateCpp(benchmark::State &state) {
+ TrackCounters track_counters;
+ auto stub =
+ grpc::testing::EchoTestService::NewStub(grpc::CreateChannelInternal(
+ "", grpc_lame_client_channel_create(
+ "localhost:1234", GRPC_STATUS_UNAUTHENTICATED, "blah")));
+ grpc::CompletionQueue cq;
+ grpc::testing::EchoRequest send_request;
+ grpc::testing::EchoResponse recv_response;
+ grpc::Status recv_status;
+ while (state.KeepRunning()) {
+ grpc::ClientContext cli_ctx;
+ auto reader = stub->AsyncEcho(&cli_ctx, send_request, &cq);
+ reader->Finish(&recv_response, &recv_status, tag(0));
+ void *t;
+ bool ok;
+ GPR_ASSERT(cq.Next(&t, &ok));
+ GPR_ASSERT(ok);
+ }
+ track_counters.Finish(state);
}
-BENCHMARK(BM_InsecureChannelWithDefaults);
+BENCHMARK(BM_LameChannelCallCreateCpp);
static void FilterDestroy(grpc_exec_ctx *exec_ctx, void *arg,
grpc_error *error) {
@@ -153,7 +232,7 @@ static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
static void DestroyCallElem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
const grpc_call_final_info *final_info,
- void *and_free_memory) {}
+ grpc_closure *then_sched_closure) {}
grpc_error *InitChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
grpc_channel_element_args *args) {
@@ -196,7 +275,7 @@ const char *name;
/* implementation of grpc_transport_init_stream */
int InitStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
grpc_stream *stream, grpc_stream_refcount *refcount,
- const void *server_data) {
+ const void *server_data, gpr_arena *arena) {
return 0;
}
@@ -220,7 +299,7 @@ void PerformOp(grpc_exec_ctx *exec_ctx, grpc_transport *self,
/* implementation of grpc_transport_destroy_stream */
void DestroyStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
- grpc_stream *stream, void *and_free_memory) {}
+ grpc_stream *stream, grpc_closure *then_sched_closure) {}
/* implementation of grpc_transport_destroy */
void Destroy(grpc_exec_ctx *exec_ctx, grpc_transport *self) {}
@@ -289,6 +368,7 @@ class SendEmptyMetadata {
// perform on said filter.
template <class Fixture, class TestOp>
static void BM_IsolatedFilter(benchmark::State &state) {
+ TrackCounters track_counters;
Fixture fixture;
std::ostringstream label;
@@ -314,7 +394,7 @@ static void BM_IsolatedFilter(benchmark::State &state) {
grpc_channel_stack *channel_stack =
static_cast<grpc_channel_stack *>(gpr_zalloc(channel_size));
GPR_ASSERT(GRPC_LOG_IF_ERROR(
- "call_stack_init",
+ "channel_stack_init",
grpc_channel_stack_init(&exec_ctx, 1, FilterDestroy, channel_stack,
&filters[0], filters.size(), &channel_args,
fixture.flags & REQUIRES_TRANSPORT
@@ -329,21 +409,36 @@ static void BM_IsolatedFilter(benchmark::State &state) {
grpc_slice method = grpc_slice_from_static_string("/foo/bar");
grpc_call_final_info final_info;
TestOp test_op_data;
+ grpc_call_element_args call_args;
+ call_args.call_stack = call_stack;
+ call_args.server_transport_data = NULL;
+ call_args.context = NULL;
+ call_args.path = method;
+ call_args.start_time = start_time;
+ call_args.deadline = deadline;
+ const int kArenaSize = 4096;
+ call_args.arena = gpr_arena_create(kArenaSize);
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(grpc_call_stack_init(&exec_ctx, channel_stack, 1,
- DoNothing, NULL, NULL, NULL, method,
- start_time, deadline, call_stack));
+ DoNothing, NULL, &call_args));
typename TestOp::Op op(&exec_ctx, &test_op_data, call_stack);
grpc_call_stack_destroy(&exec_ctx, call_stack, &final_info, NULL);
op.Finish(&exec_ctx);
grpc_exec_ctx_flush(&exec_ctx);
+ // recreate arena every 64k iterations to avoid oom
+ if (0 == (state.iterations() & 0xffff)) {
+ gpr_arena_destroy(call_args.arena);
+ call_args.arena = gpr_arena_create(kArenaSize);
+ }
}
+ gpr_arena_destroy(call_args.arena);
grpc_channel_stack_destroy(&exec_ctx, channel_stack);
grpc_exec_ctx_finish(&exec_ctx);
gpr_free(channel_stack);
gpr_free(call_stack);
state.SetLabel(label.str());
+ track_counters.Finish(state);
}
typedef Fixture<nullptr, 0> NoFilter;
diff --git a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
index 5fb3f37130..563db758f7 100644
--- a/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
+++ b/test/cpp/microbenchmarks/bm_chttp2_hpack.cc
@@ -42,18 +42,17 @@ extern "C" {
#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/static_metadata.h"
}
+#include "test/cpp/microbenchmarks/helpers.h"
#include "third_party/benchmark/include/benchmark/benchmark.h"
-static struct Init {
- Init() { grpc_init(); }
- ~Init() { grpc_shutdown(); }
-} g_init;
+auto &force_library_initialization = Library::get();
////////////////////////////////////////////////////////////////////////////////
// HPACK encoder
//
static void BM_HpackEncoderInitDestroy(benchmark::State &state) {
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_chttp2_hpack_compressor c;
while (state.KeepRunning()) {
@@ -62,11 +61,13 @@ static void BM_HpackEncoderInitDestroy(benchmark::State &state) {
grpc_exec_ctx_flush(&exec_ctx);
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_HpackEncoderInitDestroy);
template <class Fixture>
static void BM_HpackEncoderEncodeHeader(benchmark::State &state) {
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_metadata_batch b;
@@ -102,6 +103,7 @@ static void BM_HpackEncoderEncodeHeader(benchmark::State &state) {
<< " header_bytes/iter:" << (static_cast<double>(stats.header_bytes) /
static_cast<double>(state.iterations()));
state.SetLabel(label.str());
+ track_counters.Finish(state);
}
namespace hpack_encoder_fixtures {
@@ -216,6 +218,7 @@ BENCHMARK_TEMPLATE(BM_HpackEncoderEncodeHeader,
//
static void BM_HpackParserInitDestroy(benchmark::State &state) {
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_chttp2_hpack_parser p;
while (state.KeepRunning()) {
@@ -224,6 +227,7 @@ static void BM_HpackParserInitDestroy(benchmark::State &state) {
grpc_exec_ctx_flush(&exec_ctx);
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_HpackParserInitDestroy);
@@ -234,6 +238,7 @@ static void UnrefHeader(grpc_exec_ctx *exec_ctx, void *user_data,
template <class Fixture>
static void BM_HpackParserParseHeader(benchmark::State &state) {
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
std::vector<grpc_slice> init_slices = Fixture::GetInitSlices();
std::vector<grpc_slice> benchmark_slices = Fixture::GetBenchmarkSlices();
@@ -252,6 +257,7 @@ static void BM_HpackParserParseHeader(benchmark::State &state) {
}
grpc_chttp2_hpack_parser_destroy(&exec_ctx, &p);
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
namespace hpack_parser_fixtures {
diff --git a/test/cpp/microbenchmarks/bm_closure.cc b/test/cpp/microbenchmarks/bm_closure.cc
index 1f54e8c8b1..28a385b6c1 100644
--- a/test/cpp/microbenchmarks/bm_closure.cc
+++ b/test/cpp/microbenchmarks/bm_closure.cc
@@ -1,6 +1,6 @@
/*
*
- * Copyright 2015, Google Inc.
+ * Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -42,86 +42,47 @@ extern "C" {
#include "src/core/lib/support/spinlock.h"
}
+#include "test/cpp/microbenchmarks/helpers.h"
#include "third_party/benchmark/include/benchmark/benchmark.h"
-#include <sstream>
-
-#ifdef GPR_LOW_LEVEL_COUNTERS
-extern "C" gpr_atm gpr_mu_locks;
-#endif
-
-static class InitializeStuff {
- public:
- InitializeStuff() { grpc_init(); }
- ~InitializeStuff() { grpc_shutdown(); }
-} initialize_stuff;
-
-class TrackCounters {
- public:
- TrackCounters(benchmark::State& state) : state_(state) {}
-
- ~TrackCounters() {
- std::ostringstream out;
-#ifdef GPR_LOW_LEVEL_COUNTERS
- out << " locks/iter:" << ((double)(gpr_atm_no_barrier_load(&gpr_mu_locks) -
- mu_locks_at_start_) /
- (double)state_.iterations())
- << " atm_cas/iter:"
- << ((double)(gpr_atm_no_barrier_load(&gpr_counter_atm_cas) -
- atm_cas_at_start_) /
- (double)state_.iterations())
- << " atm_add/iter:"
- << ((double)(gpr_atm_no_barrier_load(&gpr_counter_atm_add) -
- atm_add_at_start_) /
- (double)state_.iterations());
-#endif
- state_.SetLabel(out.str());
- }
-
- private:
- benchmark::State& state_;
-#ifdef GPR_LOW_LEVEL_COUNTERS
- const size_t mu_locks_at_start_ = gpr_atm_no_barrier_load(&gpr_mu_locks);
- const size_t atm_cas_at_start_ =
- gpr_atm_no_barrier_load(&gpr_counter_atm_cas);
- const size_t atm_add_at_start_ =
- gpr_atm_no_barrier_load(&gpr_counter_atm_add);
-#endif
-};
+auto& force_library_initialization = Library::get();
static void BM_NoOpExecCtx(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
while (state.KeepRunning()) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_exec_ctx_finish(&exec_ctx);
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_NoOpExecCtx);
static void BM_WellFlushed(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
while (state.KeepRunning()) {
grpc_exec_ctx_flush(&exec_ctx);
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_WellFlushed);
static void DoNothing(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {}
static void BM_ClosureInitAgainstExecCtx(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_closure c;
while (state.KeepRunning()) {
benchmark::DoNotOptimize(
grpc_closure_init(&c, DoNothing, NULL, grpc_schedule_on_exec_ctx));
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureInitAgainstExecCtx);
static void BM_ClosureInitAgainstCombiner(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_combiner* combiner = grpc_combiner_create(NULL);
grpc_closure c;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -131,11 +92,12 @@ static void BM_ClosureInitAgainstCombiner(benchmark::State& state) {
}
GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureInitAgainstCombiner);
static void BM_ClosureRunOnExecCtx(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_closure c;
grpc_closure_init(&c, DoNothing, NULL, grpc_schedule_on_exec_ctx);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -144,11 +106,12 @@ static void BM_ClosureRunOnExecCtx(benchmark::State& state) {
grpc_exec_ctx_flush(&exec_ctx);
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureRunOnExecCtx);
static void BM_ClosureCreateAndRun(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
while (state.KeepRunning()) {
grpc_closure_run(&exec_ctx, grpc_closure_create(DoNothing, NULL,
@@ -156,11 +119,12 @@ static void BM_ClosureCreateAndRun(benchmark::State& state) {
GRPC_ERROR_NONE);
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureCreateAndRun);
static void BM_ClosureInitAndRun(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_closure c;
while (state.KeepRunning()) {
@@ -169,11 +133,12 @@ static void BM_ClosureInitAndRun(benchmark::State& state) {
GRPC_ERROR_NONE);
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureInitAndRun);
static void BM_ClosureSchedOnExecCtx(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_closure c;
grpc_closure_init(&c, DoNothing, NULL, grpc_schedule_on_exec_ctx);
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -182,11 +147,12 @@ static void BM_ClosureSchedOnExecCtx(benchmark::State& state) {
grpc_exec_ctx_flush(&exec_ctx);
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureSchedOnExecCtx);
static void BM_ClosureSched2OnExecCtx(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_closure c1;
grpc_closure c2;
grpc_closure_init(&c1, DoNothing, NULL, grpc_schedule_on_exec_ctx);
@@ -198,11 +164,12 @@ static void BM_ClosureSched2OnExecCtx(benchmark::State& state) {
grpc_exec_ctx_flush(&exec_ctx);
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureSched2OnExecCtx);
static void BM_ClosureSched3OnExecCtx(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_closure c1;
grpc_closure c2;
grpc_closure c3;
@@ -217,11 +184,12 @@ static void BM_ClosureSched3OnExecCtx(benchmark::State& state) {
grpc_exec_ctx_flush(&exec_ctx);
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureSched3OnExecCtx);
static void BM_AcquireMutex(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
// for comparison with the combiner stuff below
gpr_mu mu;
gpr_mu_init(&mu);
@@ -232,11 +200,12 @@ static void BM_AcquireMutex(benchmark::State& state) {
gpr_mu_unlock(&mu);
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_AcquireMutex);
static void BM_TryAcquireMutex(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
// for comparison with the combiner stuff below
gpr_mu mu;
gpr_mu_init(&mu);
@@ -250,11 +219,12 @@ static void BM_TryAcquireMutex(benchmark::State& state) {
}
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_TryAcquireMutex);
static void BM_AcquireSpinlock(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
// for comparison with the combiner stuff below
gpr_spinlock mu = GPR_SPINLOCK_INITIALIZER;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -264,11 +234,12 @@ static void BM_AcquireSpinlock(benchmark::State& state) {
gpr_spinlock_unlock(&mu);
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_AcquireSpinlock);
static void BM_TryAcquireSpinlock(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
// for comparison with the combiner stuff below
gpr_spinlock mu = GPR_SPINLOCK_INITIALIZER;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -281,11 +252,12 @@ static void BM_TryAcquireSpinlock(benchmark::State& state) {
}
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_TryAcquireSpinlock);
static void BM_ClosureSchedOnCombiner(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_combiner* combiner = grpc_combiner_create(NULL);
grpc_closure c;
grpc_closure_init(&c, DoNothing, NULL,
@@ -297,11 +269,12 @@ static void BM_ClosureSchedOnCombiner(benchmark::State& state) {
}
GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureSchedOnCombiner);
static void BM_ClosureSched2OnCombiner(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_combiner* combiner = grpc_combiner_create(NULL);
grpc_closure c1;
grpc_closure c2;
@@ -317,11 +290,12 @@ static void BM_ClosureSched2OnCombiner(benchmark::State& state) {
}
GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureSched2OnCombiner);
static void BM_ClosureSched3OnCombiner(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_combiner* combiner = grpc_combiner_create(NULL);
grpc_closure c1;
grpc_closure c2;
@@ -341,11 +315,12 @@ static void BM_ClosureSched3OnCombiner(benchmark::State& state) {
}
GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureSched3OnCombiner);
static void BM_ClosureSched2OnTwoCombiners(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_combiner* combiner1 = grpc_combiner_create(NULL);
grpc_combiner* combiner2 = grpc_combiner_create(NULL);
grpc_closure c1;
@@ -363,11 +338,12 @@ static void BM_ClosureSched2OnTwoCombiners(benchmark::State& state) {
GRPC_COMBINER_UNREF(&exec_ctx, combiner1, "finished");
GRPC_COMBINER_UNREF(&exec_ctx, combiner2, "finished");
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureSched2OnTwoCombiners);
static void BM_ClosureSched4OnTwoCombiners(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_combiner* combiner1 = grpc_combiner_create(NULL);
grpc_combiner* combiner2 = grpc_combiner_create(NULL);
grpc_closure c1;
@@ -393,6 +369,7 @@ static void BM_ClosureSched4OnTwoCombiners(benchmark::State& state) {
GRPC_COMBINER_UNREF(&exec_ctx, combiner1, "finished");
GRPC_COMBINER_UNREF(&exec_ctx, combiner2, "finished");
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureSched4OnTwoCombiners);
@@ -428,16 +405,17 @@ class Rescheduler {
};
static void BM_ClosureReschedOnExecCtx(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Rescheduler r(state, grpc_schedule_on_exec_ctx);
r.ScheduleFirst(&exec_ctx);
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureReschedOnExecCtx);
static void BM_ClosureReschedOnCombiner(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_combiner* combiner = grpc_combiner_create(NULL);
Rescheduler r(state, grpc_combiner_scheduler(combiner, false));
@@ -445,11 +423,12 @@ static void BM_ClosureReschedOnCombiner(benchmark::State& state) {
grpc_exec_ctx_flush(&exec_ctx);
GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureReschedOnCombiner);
static void BM_ClosureReschedOnCombinerFinally(benchmark::State& state) {
- TrackCounters track_counters(state);
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_combiner* combiner = grpc_combiner_create(NULL);
Rescheduler r(state, grpc_combiner_finally_scheduler(combiner, false));
@@ -458,6 +437,7 @@ static void BM_ClosureReschedOnCombinerFinally(benchmark::State& state) {
grpc_exec_ctx_flush(&exec_ctx);
GRPC_COMBINER_UNREF(&exec_ctx, combiner, "finished");
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ClosureReschedOnCombinerFinally);
diff --git a/test/cpp/microbenchmarks/bm_cq.cc b/test/cpp/microbenchmarks/bm_cq.cc
index c017474bf4..91e6a85101 100644
--- a/test/cpp/microbenchmarks/bm_cq.cc
+++ b/test/cpp/microbenchmarks/bm_cq.cc
@@ -38,6 +38,7 @@
#include <grpc++/impl/grpc_library.h>
#include <grpc/grpc.h>
+#include "test/cpp/microbenchmarks/helpers.h"
#include "third_party/benchmark/include/benchmark/benchmark.h"
extern "C" {
@@ -47,27 +48,23 @@ extern "C" {
namespace grpc {
namespace testing {
-static class InitializeStuff {
- public:
- InitializeStuff() { init_lib_.init(); }
- ~InitializeStuff() { init_lib_.shutdown(); }
-
- private:
- internal::GrpcLibrary init_lib_;
- internal::GrpcLibraryInitializer init_;
-} initialize_stuff;
+auto& force_library_initialization = Library::get();
static void BM_CreateDestroyCpp(benchmark::State& state) {
+ TrackCounters track_counters;
while (state.KeepRunning()) {
CompletionQueue cq;
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_CreateDestroyCpp);
static void BM_CreateDestroyCore(benchmark::State& state) {
+ TrackCounters track_counters;
while (state.KeepRunning()) {
grpc_completion_queue_destroy(grpc_completion_queue_create(NULL));
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_CreateDestroyCore);
@@ -80,6 +77,7 @@ class DummyTag final : public CompletionQueueTag {
};
static void BM_Pass1Cpp(benchmark::State& state) {
+ TrackCounters track_counters;
CompletionQueue cq;
grpc_completion_queue* c_cq = cq.cq();
while (state.KeepRunning()) {
@@ -94,10 +92,12 @@ static void BM_Pass1Cpp(benchmark::State& state) {
bool ok;
cq.Next(&tag, &ok);
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_Pass1Cpp);
static void BM_Pass1Core(benchmark::State& state) {
+ TrackCounters track_counters;
grpc_completion_queue* cq = grpc_completion_queue_create(NULL);
gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
while (state.KeepRunning()) {
@@ -110,10 +110,12 @@ static void BM_Pass1Core(benchmark::State& state) {
grpc_completion_queue_next(cq, deadline, NULL);
}
grpc_completion_queue_destroy(cq);
+ track_counters.Finish(state);
}
BENCHMARK(BM_Pass1Core);
static void BM_Pluck1Core(benchmark::State& state) {
+ TrackCounters track_counters;
grpc_completion_queue* cq = grpc_completion_queue_create(NULL);
gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
while (state.KeepRunning()) {
@@ -126,16 +128,19 @@ static void BM_Pluck1Core(benchmark::State& state) {
grpc_completion_queue_pluck(cq, NULL, deadline, NULL);
}
grpc_completion_queue_destroy(cq);
+ track_counters.Finish(state);
}
BENCHMARK(BM_Pluck1Core);
static void BM_EmptyCore(benchmark::State& state) {
+ TrackCounters track_counters;
grpc_completion_queue* cq = grpc_completion_queue_create(NULL);
gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
while (state.KeepRunning()) {
grpc_completion_queue_next(cq, deadline, NULL);
}
grpc_completion_queue_destroy(cq);
+ track_counters.Finish(state);
}
BENCHMARK(BM_EmptyCore);
diff --git a/test/cpp/microbenchmarks/bm_error.cc b/test/cpp/microbenchmarks/bm_error.cc
index 8a4b86f281..c4f6aa19d5 100644
--- a/test/cpp/microbenchmarks/bm_error.cc
+++ b/test/cpp/microbenchmarks/bm_error.cc
@@ -40,8 +40,11 @@ extern "C" {
#include "src/core/lib/transport/error_utils.h"
}
+#include "test/cpp/microbenchmarks/helpers.h"
#include "third_party/benchmark/include/benchmark/benchmark.h"
+auto& force_library_initialization = Library::get();
+
class ErrorDeleter {
public:
void operator()(grpc_error* error) { GRPC_ERROR_UNREF(error); }
@@ -49,31 +52,74 @@ class ErrorDeleter {
typedef std::unique_ptr<grpc_error, ErrorDeleter> ErrorPtr;
static void BM_ErrorCreate(benchmark::State& state) {
+ TrackCounters track_counters;
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(GRPC_ERROR_CREATE("Error"));
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_ErrorCreate);
static void BM_ErrorCreateAndSetStatus(benchmark::State& state) {
+ TrackCounters track_counters;
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(grpc_error_set_int(GRPC_ERROR_CREATE("Error"),
GRPC_ERROR_INT_GRPC_STATUS,
GRPC_STATUS_ABORTED));
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_ErrorCreateAndSetStatus);
+static void BM_ErrorCreateAndSetIntAndStr(benchmark::State& state) {
+ TrackCounters track_counters;
+ while (state.KeepRunning()) {
+ GRPC_ERROR_UNREF(grpc_error_set_str(
+ grpc_error_set_int(GRPC_ERROR_CREATE("GOAWAY received"),
+ GRPC_ERROR_INT_HTTP2_ERROR, (intptr_t)0),
+ GRPC_ERROR_STR_RAW_BYTES, "raw bytes"));
+ }
+ track_counters.Finish(state);
+}
+BENCHMARK(BM_ErrorCreateAndSetIntAndStr);
+
+static void BM_ErrorCreateAndSetIntLoop(benchmark::State& state) {
+ TrackCounters track_counters;
+ grpc_error* error = GRPC_ERROR_CREATE("Error");
+ int n = 0;
+ while (state.KeepRunning()) {
+ error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, n++);
+ }
+ GRPC_ERROR_UNREF(error);
+ track_counters.Finish(state);
+}
+BENCHMARK(BM_ErrorCreateAndSetIntLoop);
+
+static void BM_ErrorCreateAndSetStrLoop(benchmark::State& state) {
+ TrackCounters track_counters;
+ grpc_error* error = GRPC_ERROR_CREATE("Error");
+ const char* str = "hello";
+ while (state.KeepRunning()) {
+ error = grpc_error_set_str(error, GRPC_ERROR_STR_GRPC_MESSAGE, str);
+ }
+ GRPC_ERROR_UNREF(error);
+ track_counters.Finish(state);
+}
+BENCHMARK(BM_ErrorCreateAndSetStrLoop);
+
static void BM_ErrorRefUnref(benchmark::State& state) {
+ TrackCounters track_counters;
grpc_error* error = GRPC_ERROR_CREATE("Error");
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(GRPC_ERROR_REF(error));
}
GRPC_ERROR_UNREF(error);
+ track_counters.Finish(state);
}
BENCHMARK(BM_ErrorRefUnref);
static void BM_ErrorUnrefNone(benchmark::State& state) {
+ TrackCounters track_counters;
while (state.KeepRunning()) {
GRPC_ERROR_UNREF(GRPC_ERROR_NONE);
}
@@ -81,30 +127,36 @@ static void BM_ErrorUnrefNone(benchmark::State& state) {
BENCHMARK(BM_ErrorUnrefNone);
static void BM_ErrorGetIntFromNoError(benchmark::State& state) {
+ TrackCounters track_counters;
while (state.KeepRunning()) {
intptr_t value;
grpc_error_get_int(GRPC_ERROR_NONE, GRPC_ERROR_INT_GRPC_STATUS, &value);
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_ErrorGetIntFromNoError);
static void BM_ErrorGetMissingInt(benchmark::State& state) {
+ TrackCounters track_counters;
ErrorPtr error(
grpc_error_set_int(GRPC_ERROR_CREATE("Error"), GRPC_ERROR_INT_INDEX, 1));
while (state.KeepRunning()) {
intptr_t value;
grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_ErrorGetMissingInt);
static void BM_ErrorGetPresentInt(benchmark::State& state) {
+ TrackCounters track_counters;
ErrorPtr error(
grpc_error_set_int(GRPC_ERROR_CREATE("Error"), GRPC_ERROR_INT_OFFSET, 1));
while (state.KeepRunning()) {
intptr_t value;
grpc_error_get_int(error.get(), GRPC_ERROR_INT_OFFSET, &value);
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_ErrorGetPresentInt);
@@ -177,22 +229,27 @@ class ErrorWithNestedGrpcStatus {
template <class Fixture>
static void BM_ErrorStringOnNewError(benchmark::State& state) {
+ TrackCounters track_counters;
while (state.KeepRunning()) {
Fixture fixture;
grpc_error_string(fixture.error());
}
+ track_counters.Finish(state);
}
template <class Fixture>
static void BM_ErrorStringRepeatedly(benchmark::State& state) {
+ TrackCounters track_counters;
Fixture fixture;
while (state.KeepRunning()) {
grpc_error_string(fixture.error());
}
+ track_counters.Finish(state);
}
template <class Fixture>
static void BM_ErrorGetStatus(benchmark::State& state) {
+ TrackCounters track_counters;
Fixture fixture;
while (state.KeepRunning()) {
grpc_status_code status;
@@ -200,34 +257,41 @@ static void BM_ErrorGetStatus(benchmark::State& state) {
grpc_error_get_status(fixture.error(), fixture.deadline(), &status, &msg,
NULL);
}
+ track_counters.Finish(state);
}
template <class Fixture>
static void BM_ErrorGetStatusCode(benchmark::State& state) {
+ TrackCounters track_counters;
Fixture fixture;
while (state.KeepRunning()) {
grpc_status_code status;
grpc_error_get_status(fixture.error(), fixture.deadline(), &status, NULL,
NULL);
}
+ track_counters.Finish(state);
}
template <class Fixture>
static void BM_ErrorHttpError(benchmark::State& state) {
+ TrackCounters track_counters;
Fixture fixture;
while (state.KeepRunning()) {
grpc_http2_error_code error;
grpc_error_get_status(fixture.error(), fixture.deadline(), NULL, NULL,
&error);
}
+ track_counters.Finish(state);
}
template <class Fixture>
static void BM_HasClearGrpcStatus(benchmark::State& state) {
+ TrackCounters track_counters;
Fixture fixture;
while (state.KeepRunning()) {
grpc_error_has_clear_grpc_status(fixture.error());
}
+ track_counters.Finish(state);
}
#define BENCHMARK_SUITE(fixture) \
diff --git a/test/cpp/microbenchmarks/bm_fullstack.cc b/test/cpp/microbenchmarks/bm_fullstack.cc
deleted file mode 100644
index 48e131f1be..0000000000
--- a/test/cpp/microbenchmarks/bm_fullstack.cc
+++ /dev/null
@@ -1,1079 +0,0 @@
-/*
- *
- * Copyright 2016, 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.
- *
- */
-
-/* Benchmark gRPC end2end in various configurations */
-
-#include <sstream>
-
-#include <grpc++/channel.h>
-#include <grpc++/create_channel.h>
-#include <grpc++/impl/grpc_library.h>
-#include <grpc++/security/credentials.h>
-#include <grpc++/security/server_credentials.h>
-#include <grpc++/server.h>
-#include <grpc++/server_builder.h>
-#include <grpc/support/log.h>
-
-extern "C" {
-#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
-#include "src/core/ext/transport/chttp2/transport/internal.h"
-#include "src/core/lib/channel/channel_args.h"
-#include "src/core/lib/iomgr/endpoint.h"
-#include "src/core/lib/iomgr/endpoint_pair.h"
-#include "src/core/lib/iomgr/exec_ctx.h"
-#include "src/core/lib/iomgr/tcp_posix.h"
-#include "src/core/lib/surface/channel.h"
-#include "src/core/lib/surface/completion_queue.h"
-#include "src/core/lib/surface/server.h"
-#include "test/core/util/memory_counters.h"
-#include "test/core/util/passthru_endpoint.h"
-#include "test/core/util/port.h"
-#include "test/core/util/trickle_endpoint.h"
-}
-#include "src/core/lib/profiling/timers.h"
-#include "src/cpp/client/create_channel_internal.h"
-#include "src/proto/grpc/testing/echo.grpc.pb.h"
-#include "third_party/benchmark/include/benchmark/benchmark.h"
-
-namespace grpc {
-namespace testing {
-
-static class InitializeStuff {
- public:
- InitializeStuff() {
- grpc_memory_counters_init();
- init_lib_.init();
- rq_ = grpc_resource_quota_create("bm");
- }
-
- ~InitializeStuff() { init_lib_.shutdown(); }
-
- grpc_resource_quota* rq() { return rq_; }
-
- private:
- internal::GrpcLibrary init_lib_;
- grpc_resource_quota* rq_;
-} initialize_stuff;
-
-/*******************************************************************************
- * FIXTURES
- */
-
-static void ApplyCommonServerBuilderConfig(ServerBuilder* b) {
- b->SetMaxReceiveMessageSize(INT_MAX);
- b->SetMaxSendMessageSize(INT_MAX);
-}
-
-static void ApplyCommonChannelArguments(ChannelArguments* c) {
- c->SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, INT_MAX);
- c->SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, INT_MAX);
-}
-
-#ifdef GPR_LOW_LEVEL_COUNTERS
-extern "C" gpr_atm gpr_mu_locks;
-extern "C" gpr_atm gpr_counter_atm_cas;
-extern "C" gpr_atm gpr_counter_atm_add;
-#endif
-
-class BaseFixture {
- public:
- void Finish(benchmark::State& s) {
- std::ostringstream out;
- this->AddToLabel(out, s);
-#ifdef GPR_LOW_LEVEL_COUNTERS
- out << " locks/iter:" << ((double)(gpr_atm_no_barrier_load(&gpr_mu_locks) -
- mu_locks_at_start_) /
- (double)s.iterations())
- << " atm_cas/iter:"
- << ((double)(gpr_atm_no_barrier_load(&gpr_counter_atm_cas) -
- atm_cas_at_start_) /
- (double)s.iterations())
- << " atm_add/iter:"
- << ((double)(gpr_atm_no_barrier_load(&gpr_counter_atm_add) -
- atm_add_at_start_) /
- (double)s.iterations());
-#endif
- grpc_memory_counters counters_at_end = grpc_memory_counters_snapshot();
- out << " allocs/iter:"
- << ((double)(counters_at_end.total_allocs_absolute -
- counters_at_start_.total_allocs_absolute) /
- (double)s.iterations());
- auto label = out.str();
- if (label.length() && label[0] == ' ') {
- label = label.substr(1);
- }
- s.SetLabel(label);
- }
-
- virtual void AddToLabel(std::ostream& out, benchmark::State& s) = 0;
-
- private:
-#ifdef GPR_LOW_LEVEL_COUNTERS
- const size_t mu_locks_at_start_ = gpr_atm_no_barrier_load(&gpr_mu_locks);
- const size_t atm_cas_at_start_ =
- gpr_atm_no_barrier_load(&gpr_counter_atm_cas);
- const size_t atm_add_at_start_ =
- gpr_atm_no_barrier_load(&gpr_counter_atm_add);
-#endif
- grpc_memory_counters counters_at_start_ = grpc_memory_counters_snapshot();
-};
-
-class FullstackFixture : public BaseFixture {
- public:
- FullstackFixture(Service* service, const grpc::string& address) {
- ServerBuilder b;
- b.AddListeningPort(address, InsecureServerCredentials());
- cq_ = b.AddCompletionQueue(true);
- b.RegisterService(service);
- ApplyCommonServerBuilderConfig(&b);
- server_ = b.BuildAndStart();
- ChannelArguments args;
- ApplyCommonChannelArguments(&args);
- channel_ = CreateCustomChannel(address, InsecureChannelCredentials(), args);
- }
-
- virtual ~FullstackFixture() {
- server_->Shutdown();
- cq_->Shutdown();
- void* tag;
- bool ok;
- while (cq_->Next(&tag, &ok)) {
- }
- }
-
- ServerCompletionQueue* cq() { return cq_.get(); }
- std::shared_ptr<Channel> channel() { return channel_; }
-
- private:
- std::unique_ptr<Server> server_;
- std::unique_ptr<ServerCompletionQueue> cq_;
- std::shared_ptr<Channel> channel_;
-};
-
-class TCP : public FullstackFixture {
- public:
- TCP(Service* service) : FullstackFixture(service, MakeAddress()) {}
-
- void AddToLabel(std::ostream& out, benchmark::State& state) {}
-
- private:
- static grpc::string MakeAddress() {
- int port = grpc_pick_unused_port_or_die();
- std::stringstream addr;
- addr << "localhost:" << port;
- return addr.str();
- }
-};
-
-class UDS : public FullstackFixture {
- public:
- UDS(Service* service) : FullstackFixture(service, MakeAddress()) {}
-
- void AddToLabel(std::ostream& out, benchmark::State& state) override {}
-
- private:
- static grpc::string MakeAddress() {
- int port = grpc_pick_unused_port_or_die(); // just for a unique id - not a
- // real port
- std::stringstream addr;
- addr << "unix:/tmp/bm_fullstack." << port;
- return addr.str();
- }
-};
-
-class EndpointPairFixture : public BaseFixture {
- public:
- EndpointPairFixture(Service* service, grpc_endpoint_pair endpoints)
- : endpoint_pair_(endpoints) {
- ServerBuilder b;
- cq_ = b.AddCompletionQueue(true);
- b.RegisterService(service);
- ApplyCommonServerBuilderConfig(&b);
- server_ = b.BuildAndStart();
-
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-
- /* add server endpoint to server_ */
- {
- const grpc_channel_args* server_args =
- grpc_server_get_channel_args(server_->c_server());
- server_transport_ = grpc_create_chttp2_transport(
- &exec_ctx, server_args, endpoints.server, 0 /* is_client */);
-
- grpc_pollset** pollsets;
- size_t num_pollsets = 0;
- grpc_server_get_pollsets(server_->c_server(), &pollsets, &num_pollsets);
-
- for (size_t i = 0; i < num_pollsets; i++) {
- grpc_endpoint_add_to_pollset(&exec_ctx, endpoints.server, pollsets[i]);
- }
-
- grpc_server_setup_transport(&exec_ctx, server_->c_server(),
- server_transport_, NULL, server_args);
- grpc_chttp2_transport_start_reading(&exec_ctx, server_transport_, NULL);
- }
-
- /* create channel */
- {
- ChannelArguments args;
- args.SetString(GRPC_ARG_DEFAULT_AUTHORITY, "test.authority");
- ApplyCommonChannelArguments(&args);
-
- grpc_channel_args c_args = args.c_channel_args();
- client_transport_ =
- grpc_create_chttp2_transport(&exec_ctx, &c_args, endpoints.client, 1);
- GPR_ASSERT(client_transport_);
- grpc_channel* channel =
- grpc_channel_create(&exec_ctx, "target", &c_args,
- GRPC_CLIENT_DIRECT_CHANNEL, client_transport_);
- grpc_chttp2_transport_start_reading(&exec_ctx, client_transport_, NULL);
-
- channel_ = CreateChannelInternal("", channel);
- }
-
- grpc_exec_ctx_finish(&exec_ctx);
- }
-
- virtual ~EndpointPairFixture() {
- server_->Shutdown();
- cq_->Shutdown();
- void* tag;
- bool ok;
- while (cq_->Next(&tag, &ok)) {
- }
- }
-
- ServerCompletionQueue* cq() { return cq_.get(); }
- std::shared_ptr<Channel> channel() { return channel_; }
-
- protected:
- grpc_endpoint_pair endpoint_pair_;
- grpc_transport* client_transport_;
- grpc_transport* server_transport_;
-
- private:
- std::unique_ptr<Server> server_;
- std::unique_ptr<ServerCompletionQueue> cq_;
- std::shared_ptr<Channel> channel_;
-};
-
-class SockPair : public EndpointPairFixture {
- public:
- SockPair(Service* service)
- : EndpointPairFixture(service, grpc_iomgr_create_endpoint_pair(
- "test", initialize_stuff.rq(), 8192)) {
- }
-
- void AddToLabel(std::ostream& out, benchmark::State& state) {}
-};
-
-class InProcessCHTTP2 : public EndpointPairFixture {
- public:
- InProcessCHTTP2(Service* service)
- : EndpointPairFixture(service, MakeEndpoints()) {}
-
- void AddToLabel(std::ostream& out, benchmark::State& state) {
- out << " writes/iter:"
- << ((double)stats_.num_writes / (double)state.iterations());
- }
-
- private:
- grpc_passthru_endpoint_stats stats_;
-
- grpc_endpoint_pair MakeEndpoints() {
- grpc_endpoint_pair p;
- grpc_passthru_endpoint_create(&p.client, &p.server, initialize_stuff.rq(),
- &stats_);
- return p;
- }
-};
-
-class TrickledCHTTP2 : public EndpointPairFixture {
- public:
- TrickledCHTTP2(Service* service, size_t megabits_per_second)
- : EndpointPairFixture(service, MakeEndpoints(megabits_per_second)) {}
-
- void AddToLabel(std::ostream& out, benchmark::State& state) {
- out << " writes/iter:"
- << ((double)stats_.num_writes / (double)state.iterations())
- << " cli_transport_stalls/iter:"
- << ((double)
- client_stats_.streams_stalled_due_to_transport_flow_control /
- (double)state.iterations())
- << " cli_stream_stalls/iter:"
- << ((double)client_stats_.streams_stalled_due_to_stream_flow_control /
- (double)state.iterations())
- << " svr_transport_stalls/iter:"
- << ((double)
- server_stats_.streams_stalled_due_to_transport_flow_control /
- (double)state.iterations())
- << " svr_stream_stalls/iter:"
- << ((double)server_stats_.streams_stalled_due_to_stream_flow_control /
- (double)state.iterations());
- }
-
- void Step() {
- grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
- size_t client_backlog =
- grpc_trickle_endpoint_trickle(&exec_ctx, endpoint_pair_.client);
- size_t server_backlog =
- grpc_trickle_endpoint_trickle(&exec_ctx, endpoint_pair_.server);
- grpc_exec_ctx_finish(&exec_ctx);
-
- UpdateStats((grpc_chttp2_transport*)client_transport_, &client_stats_,
- client_backlog);
- UpdateStats((grpc_chttp2_transport*)server_transport_, &server_stats_,
- server_backlog);
- }
-
- private:
- grpc_passthru_endpoint_stats stats_;
- struct Stats {
- int streams_stalled_due_to_stream_flow_control = 0;
- int streams_stalled_due_to_transport_flow_control = 0;
- };
- Stats client_stats_;
- Stats server_stats_;
-
- grpc_endpoint_pair MakeEndpoints(size_t kilobits) {
- grpc_endpoint_pair p;
- grpc_passthru_endpoint_create(&p.client, &p.server, initialize_stuff.rq(),
- &stats_);
- double bytes_per_second = 125.0 * kilobits;
- p.client = grpc_trickle_endpoint_create(p.client, bytes_per_second);
- p.server = grpc_trickle_endpoint_create(p.server, bytes_per_second);
- return p;
- }
-
- void UpdateStats(grpc_chttp2_transport* t, Stats* s, size_t backlog) {
- if (backlog == 0) {
- if (t->lists[GRPC_CHTTP2_LIST_STALLED_BY_STREAM].head != NULL) {
- s->streams_stalled_due_to_stream_flow_control++;
- }
- if (t->lists[GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT].head != NULL) {
- s->streams_stalled_due_to_transport_flow_control++;
- }
- }
- }
-};
-
-/*******************************************************************************
- * CONTEXT MUTATORS
- */
-
-static const int kPregenerateKeyCount = 100000;
-
-template <class F>
-auto MakeVector(size_t length, F f) -> std::vector<decltype(f())> {
- std::vector<decltype(f())> out;
- out.reserve(length);
- for (size_t i = 0; i < length; i++) {
- out.push_back(f());
- }
- return out;
-}
-
-class NoOpMutator {
- public:
- template <class ContextType>
- NoOpMutator(ContextType* context) {}
-};
-
-template <int length>
-class RandomBinaryMetadata {
- public:
- static const grpc::string& Key() { return kKey; }
-
- static const grpc::string& Value() {
- return kValues[rand() % kValues.size()];
- }
-
- private:
- static const grpc::string kKey;
- static const std::vector<grpc::string> kValues;
-
- static grpc::string GenerateOneString() {
- grpc::string s;
- s.reserve(length + 1);
- for (int i = 0; i < length; i++) {
- s += (char)rand();
- }
- return s;
- }
-};
-
-template <int length>
-const grpc::string RandomBinaryMetadata<length>::kKey = "foo-bin";
-
-template <int length>
-const std::vector<grpc::string> RandomBinaryMetadata<length>::kValues =
- MakeVector(kPregenerateKeyCount, GenerateOneString);
-
-template <int length>
-class RandomAsciiMetadata {
- public:
- static const grpc::string& Key() { return kKey; }
-
- static const grpc::string& Value() {
- return kValues[rand() % kValues.size()];
- }
-
- private:
- static const grpc::string kKey;
- static const std::vector<grpc::string> kValues;
-
- static grpc::string GenerateOneString() {
- grpc::string s;
- s.reserve(length + 1);
- for (int i = 0; i < length; i++) {
- s += (char)(rand() % 26 + 'a');
- }
- return s;
- }
-};
-
-template <int length>
-const grpc::string RandomAsciiMetadata<length>::kKey = "foo";
-
-template <int length>
-const std::vector<grpc::string> RandomAsciiMetadata<length>::kValues =
- MakeVector(kPregenerateKeyCount, GenerateOneString);
-
-template <class Generator, int kNumKeys>
-class Client_AddMetadata : public NoOpMutator {
- public:
- Client_AddMetadata(ClientContext* context) : NoOpMutator(context) {
- for (int i = 0; i < kNumKeys; i++) {
- context->AddMetadata(Generator::Key(), Generator::Value());
- }
- }
-};
-
-template <class Generator, int kNumKeys>
-class Server_AddInitialMetadata : public NoOpMutator {
- public:
- Server_AddInitialMetadata(ServerContext* context) : NoOpMutator(context) {
- for (int i = 0; i < kNumKeys; i++) {
- context->AddInitialMetadata(Generator::Key(), Generator::Value());
- }
- }
-};
-
-/*******************************************************************************
- * BENCHMARKING KERNELS
- */
-
-static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
-
-template <class Fixture, class ClientContextMutator, class ServerContextMutator>
-static void BM_UnaryPingPong(benchmark::State& state) {
- EchoTestService::AsyncService service;
- std::unique_ptr<Fixture> fixture(new Fixture(&service));
- EchoRequest send_request;
- EchoResponse send_response;
- EchoResponse recv_response;
- if (state.range(0) > 0) {
- send_request.set_message(std::string(state.range(0), 'a'));
- }
- if (state.range(1) > 0) {
- send_response.set_message(std::string(state.range(1), 'a'));
- }
- Status recv_status;
- struct ServerEnv {
- ServerContext ctx;
- EchoRequest recv_request;
- grpc::ServerAsyncResponseWriter<EchoResponse> response_writer;
- ServerEnv() : response_writer(&ctx) {}
- };
- uint8_t server_env_buffer[2 * sizeof(ServerEnv)];
- ServerEnv* server_env[2] = {
- reinterpret_cast<ServerEnv*>(server_env_buffer),
- reinterpret_cast<ServerEnv*>(server_env_buffer + sizeof(ServerEnv))};
- new (server_env[0]) ServerEnv;
- new (server_env[1]) ServerEnv;
- service.RequestEcho(&server_env[0]->ctx, &server_env[0]->recv_request,
- &server_env[0]->response_writer, fixture->cq(),
- fixture->cq(), tag(0));
- service.RequestEcho(&server_env[1]->ctx, &server_env[1]->recv_request,
- &server_env[1]->response_writer, fixture->cq(),
- fixture->cq(), tag(1));
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
- while (state.KeepRunning()) {
- GPR_TIMER_SCOPE("BenchmarkCycle", 0);
- recv_response.Clear();
- ClientContext cli_ctx;
- ClientContextMutator cli_ctx_mut(&cli_ctx);
- std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
- stub->AsyncEcho(&cli_ctx, send_request, fixture->cq()));
- void* t;
- bool ok;
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- GPR_ASSERT(t == tag(0) || t == tag(1));
- intptr_t slot = reinterpret_cast<intptr_t>(t);
- ServerEnv* senv = server_env[slot];
- ServerContextMutator svr_ctx_mut(&senv->ctx);
- senv->response_writer.Finish(send_response, Status::OK, tag(3));
- response_reader->Finish(&recv_response, &recv_status, tag(4));
- for (int i = (1 << 3) | (1 << 4); i != 0;) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int tagnum = (int)reinterpret_cast<intptr_t>(t);
- GPR_ASSERT(i & (1 << tagnum));
- i -= 1 << tagnum;
- }
- GPR_ASSERT(recv_status.ok());
-
- senv->~ServerEnv();
- senv = new (senv) ServerEnv();
- service.RequestEcho(&senv->ctx, &senv->recv_request, &senv->response_writer,
- fixture->cq(), fixture->cq(), tag(slot));
- }
- fixture->Finish(state);
- fixture.reset();
- server_env[0]->~ServerEnv();
- server_env[1]->~ServerEnv();
- state.SetBytesProcessed(state.range(0) * state.iterations() +
- state.range(1) * state.iterations());
-}
-
-// Repeatedly makes Streaming Bidi calls (exchanging a configurable number of
-// messages in each call) in a loop on a single channel
-//
-// First parmeter (i.e state.range(0)): Message size (in bytes) to use
-// Second parameter (i.e state.range(1)): Number of ping pong messages.
-// Note: One ping-pong means two messages (one from client to server and
-// the other from server to client):
-template <class Fixture, class ClientContextMutator, class ServerContextMutator>
-static void BM_StreamingPingPong(benchmark::State& state) {
- const int msg_size = state.range(0);
- const int max_ping_pongs = state.range(1);
-
- EchoTestService::AsyncService service;
- std::unique_ptr<Fixture> fixture(new Fixture(&service));
- {
- EchoResponse send_response;
- EchoResponse recv_response;
- EchoRequest send_request;
- EchoRequest recv_request;
-
- if (msg_size > 0) {
- send_request.set_message(std::string(msg_size, 'a'));
- send_response.set_message(std::string(msg_size, 'b'));
- }
-
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
-
- while (state.KeepRunning()) {
- ServerContext svr_ctx;
- ServerContextMutator svr_ctx_mut(&svr_ctx);
- ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
- service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
- fixture->cq(), tag(0));
-
- ClientContext cli_ctx;
- ClientContextMutator cli_ctx_mut(&cli_ctx);
- auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
-
- // Establish async stream between client side and server side
- void* t;
- bool ok;
- int need_tags = (1 << 0) | (1 << 1);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- // Send 'max_ping_pongs' number of ping pong messages
- int ping_pong_cnt = 0;
- while (ping_pong_cnt < max_ping_pongs) {
- request_rw->Write(send_request, tag(0)); // Start client send
- response_rw.Read(&recv_request, tag(1)); // Start server recv
- request_rw->Read(&recv_response, tag(2)); // Start client recv
-
- need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
-
- // If server recv is complete, start the server send operation
- if (i == 1) {
- response_rw.Write(send_response, tag(3));
- }
-
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- ping_pong_cnt++;
- }
-
- request_rw->WritesDone(tag(0));
- response_rw.Finish(Status::OK, tag(1));
-
- Status recv_status;
- request_rw->Finish(&recv_status, tag(2));
-
- need_tags = (1 << 0) | (1 << 1) | (1 << 2);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- GPR_ASSERT(recv_status.ok());
- }
- }
-
- fixture->Finish(state);
- fixture.reset();
- state.SetBytesProcessed(msg_size * state.iterations() * max_ping_pongs * 2);
-}
-
-// Repeatedly sends ping pong messages in a single streaming Bidi call in a loop
-// First parmeter (i.e state.range(0)): Message size (in bytes) to use
-template <class Fixture, class ClientContextMutator, class ServerContextMutator>
-static void BM_StreamingPingPongMsgs(benchmark::State& state) {
- const int msg_size = state.range(0);
-
- EchoTestService::AsyncService service;
- std::unique_ptr<Fixture> fixture(new Fixture(&service));
- {
- EchoResponse send_response;
- EchoResponse recv_response;
- EchoRequest send_request;
- EchoRequest recv_request;
-
- if (msg_size > 0) {
- send_request.set_message(std::string(msg_size, 'a'));
- send_response.set_message(std::string(msg_size, 'b'));
- }
-
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
-
- ServerContext svr_ctx;
- ServerContextMutator svr_ctx_mut(&svr_ctx);
- ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
- service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
- fixture->cq(), tag(0));
-
- ClientContext cli_ctx;
- ClientContextMutator cli_ctx_mut(&cli_ctx);
- auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
-
- // Establish async stream between client side and server side
- void* t;
- bool ok;
- int need_tags = (1 << 0) | (1 << 1);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- while (state.KeepRunning()) {
- GPR_TIMER_SCOPE("BenchmarkCycle", 0);
- request_rw->Write(send_request, tag(0)); // Start client send
- response_rw.Read(&recv_request, tag(1)); // Start server recv
- request_rw->Read(&recv_response, tag(2)); // Start client recv
-
- need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
-
- // If server recv is complete, start the server send operation
- if (i == 1) {
- response_rw.Write(send_response, tag(3));
- }
-
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- }
-
- request_rw->WritesDone(tag(0));
- response_rw.Finish(Status::OK, tag(1));
- Status recv_status;
- request_rw->Finish(&recv_status, tag(2));
-
- need_tags = (1 << 0) | (1 << 1) | (1 << 2);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
-
- GPR_ASSERT(recv_status.ok());
- }
-
- fixture->Finish(state);
- fixture.reset();
- state.SetBytesProcessed(msg_size * state.iterations() * 2);
-}
-
-template <class Fixture>
-static void BM_PumpStreamClientToServer(benchmark::State& state) {
- EchoTestService::AsyncService service;
- std::unique_ptr<Fixture> fixture(new Fixture(&service));
- {
- EchoRequest send_request;
- EchoRequest recv_request;
- if (state.range(0) > 0) {
- send_request.set_message(std::string(state.range(0), 'a'));
- }
- Status recv_status;
- ServerContext svr_ctx;
- ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
- service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
- fixture->cq(), tag(0));
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
- ClientContext cli_ctx;
- auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
- int need_tags = (1 << 0) | (1 << 1);
- void* t;
- bool ok;
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- response_rw.Read(&recv_request, tag(0));
- while (state.KeepRunning()) {
- GPR_TIMER_SCOPE("BenchmarkCycle", 0);
- request_rw->Write(send_request, tag(1));
- while (true) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- if (t == tag(0)) {
- response_rw.Read(&recv_request, tag(0));
- } else if (t == tag(1)) {
- break;
- } else {
- GPR_ASSERT(false);
- }
- }
- }
- request_rw->WritesDone(tag(1));
- need_tags = (1 << 0) | (1 << 1);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- }
- fixture->Finish(state);
- fixture.reset();
- state.SetBytesProcessed(state.range(0) * state.iterations());
-}
-
-template <class Fixture>
-static void BM_PumpStreamServerToClient(benchmark::State& state) {
- EchoTestService::AsyncService service;
- std::unique_ptr<Fixture> fixture(new Fixture(&service));
- {
- EchoResponse send_response;
- EchoResponse recv_response;
- if (state.range(0) > 0) {
- send_response.set_message(std::string(state.range(0), 'a'));
- }
- Status recv_status;
- ServerContext svr_ctx;
- ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
- service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
- fixture->cq(), tag(0));
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
- ClientContext cli_ctx;
- auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
- int need_tags = (1 << 0) | (1 << 1);
- void* t;
- bool ok;
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- request_rw->Read(&recv_response, tag(0));
- while (state.KeepRunning()) {
- GPR_TIMER_SCOPE("BenchmarkCycle", 0);
- response_rw.Write(send_response, tag(1));
- while (true) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- if (t == tag(0)) {
- request_rw->Read(&recv_response, tag(0));
- } else if (t == tag(1)) {
- break;
- } else {
- GPR_ASSERT(false);
- }
- }
- }
- response_rw.Finish(Status::OK, tag(1));
- need_tags = (1 << 0) | (1 << 1);
- while (need_tags) {
- GPR_ASSERT(fixture->cq()->Next(&t, &ok));
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- }
- fixture->Finish(state);
- fixture.reset();
- state.SetBytesProcessed(state.range(0) * state.iterations());
-}
-
-static void TrickleCQNext(TrickledCHTTP2* fixture, void** t, bool* ok) {
- while (true) {
- switch (fixture->cq()->AsyncNext(
- t, ok, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
- gpr_time_from_micros(100, GPR_TIMESPAN)))) {
- case CompletionQueue::TIMEOUT:
- fixture->Step();
- break;
- case CompletionQueue::SHUTDOWN:
- GPR_ASSERT(false);
- break;
- case CompletionQueue::GOT_EVENT:
- return;
- }
- }
-}
-
-static void BM_PumpStreamServerToClient_Trickle(benchmark::State& state) {
- EchoTestService::AsyncService service;
- std::unique_ptr<TrickledCHTTP2> fixture(
- new TrickledCHTTP2(&service, state.range(1)));
- {
- EchoResponse send_response;
- EchoResponse recv_response;
- if (state.range(0) > 0) {
- send_response.set_message(std::string(state.range(0), 'a'));
- }
- Status recv_status;
- ServerContext svr_ctx;
- ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
- service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
- fixture->cq(), tag(0));
- std::unique_ptr<EchoTestService::Stub> stub(
- EchoTestService::NewStub(fixture->channel()));
- ClientContext cli_ctx;
- auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
- int need_tags = (1 << 0) | (1 << 1);
- void* t;
- bool ok;
- while (need_tags) {
- TrickleCQNext(fixture.get(), &t, &ok);
- GPR_ASSERT(ok);
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- request_rw->Read(&recv_response, tag(0));
- while (state.KeepRunning()) {
- GPR_TIMER_SCOPE("BenchmarkCycle", 0);
- response_rw.Write(send_response, tag(1));
- while (true) {
- TrickleCQNext(fixture.get(), &t, &ok);
- if (t == tag(0)) {
- request_rw->Read(&recv_response, tag(0));
- } else if (t == tag(1)) {
- break;
- } else {
- GPR_ASSERT(false);
- }
- }
- }
- response_rw.Finish(Status::OK, tag(1));
- need_tags = (1 << 0) | (1 << 1);
- while (need_tags) {
- TrickleCQNext(fixture.get(), &t, &ok);
- int i = (int)(intptr_t)t;
- GPR_ASSERT(need_tags & (1 << i));
- need_tags &= ~(1 << i);
- }
- }
- fixture->Finish(state);
- fixture.reset();
- state.SetBytesProcessed(state.range(0) * state.iterations());
-}
-
-/*******************************************************************************
- * CONFIGURATIONS
- */
-
-static void SweepSizesArgs(benchmark::internal::Benchmark* b) {
- b->Args({0, 0});
- for (int i = 1; i <= 128 * 1024 * 1024; i *= 8) {
- b->Args({i, 0});
- b->Args({0, i});
- b->Args({i, i});
- }
-}
-
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, TCP, NoOpMutator, NoOpMutator)
- ->Apply(SweepSizesArgs);
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, UDS, NoOpMutator, NoOpMutator)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, SockPair, NoOpMutator, NoOpMutator)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator, NoOpMutator)
- ->Apply(SweepSizesArgs);
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
- Client_AddMetadata<RandomBinaryMetadata<10>, 1>, NoOpMutator)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
- Client_AddMetadata<RandomBinaryMetadata<31>, 1>, NoOpMutator)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
- Client_AddMetadata<RandomBinaryMetadata<100>, 1>,
- NoOpMutator)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
- Client_AddMetadata<RandomBinaryMetadata<10>, 2>, NoOpMutator)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
- Client_AddMetadata<RandomBinaryMetadata<31>, 2>, NoOpMutator)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
- Client_AddMetadata<RandomBinaryMetadata<100>, 2>,
- NoOpMutator)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
- Server_AddInitialMetadata<RandomBinaryMetadata<10>, 1>)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
- Server_AddInitialMetadata<RandomBinaryMetadata<31>, 1>)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
- Server_AddInitialMetadata<RandomBinaryMetadata<100>, 1>)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
- Client_AddMetadata<RandomAsciiMetadata<10>, 1>, NoOpMutator)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
- Client_AddMetadata<RandomAsciiMetadata<31>, 1>, NoOpMutator)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
- Client_AddMetadata<RandomAsciiMetadata<100>, 1>, NoOpMutator)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
- Server_AddInitialMetadata<RandomAsciiMetadata<10>, 1>)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
- Server_AddInitialMetadata<RandomAsciiMetadata<31>, 1>)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
- Server_AddInitialMetadata<RandomAsciiMetadata<100>, 1>)
- ->Args({0, 0});
-BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
- Server_AddInitialMetadata<RandomAsciiMetadata<10>, 100>)
- ->Args({0, 0});
-
-BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, TCP)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, UDS)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, SockPair)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, InProcessCHTTP2)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, TCP)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, UDS)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, SockPair)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, InProcessCHTTP2)
- ->Range(0, 128 * 1024 * 1024);
-
-static void TrickleArgs(benchmark::internal::Benchmark* b) {
- for (int i = 1; i <= 128 * 1024 * 1024; i *= 8) {
- for (int j = 1; j <= 128 * 1024 * 1024; j *= 8) {
- double expected_time =
- static_cast<double>(14 + i) / (125.0 * static_cast<double>(j));
- if (expected_time > 0.01) continue;
- b->Args({i, j});
- }
- }
-}
-
-BENCHMARK(BM_PumpStreamServerToClient_Trickle)->Apply(TrickleArgs);
-
-// Generate Args for StreamingPingPong benchmarks. Currently generates args for
-// only "small streams" (i.e streams with 0, 1 or 2 messages)
-static void StreamingPingPongArgs(benchmark::internal::Benchmark* b) {
- int msg_size = 0;
-
- b->Args({0, 0}); // spl case: 0 ping-pong msgs (msg_size doesn't matter here)
-
- for (msg_size = 0; msg_size <= 128 * 1024 * 1024;
- msg_size == 0 ? msg_size++ : msg_size *= 8) {
- b->Args({msg_size, 1});
- b->Args({msg_size, 2});
- }
-}
-
-BENCHMARK_TEMPLATE(BM_StreamingPingPong, InProcessCHTTP2, NoOpMutator,
- NoOpMutator)
- ->Apply(StreamingPingPongArgs);
-BENCHMARK_TEMPLATE(BM_StreamingPingPong, TCP, NoOpMutator, NoOpMutator)
- ->Apply(StreamingPingPongArgs);
-
-BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, InProcessCHTTP2, NoOpMutator,
- NoOpMutator)
- ->Range(0, 128 * 1024 * 1024);
-BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, TCP, NoOpMutator, NoOpMutator)
- ->Range(0, 128 * 1024 * 1024);
-
-} // namespace testing
-} // namespace grpc
-
-BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
new file mode 100644
index 0000000000..00e37f7912
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_ping_pong.cc
@@ -0,0 +1,276 @@
+/*
+ *
+ * Copyright 2016, 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.
+ *
+ */
+
+/* Benchmark gRPC end2end in various configurations */
+
+#include <sstream>
+
+#include "src/core/lib/profiling/timers.h"
+#include "src/cpp/client/create_channel_internal.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
+#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+namespace grpc {
+namespace testing {
+
+// force library initialization
+auto& force_library_initialization = Library::get();
+
+/*******************************************************************************
+ * BENCHMARKING KERNELS
+ */
+
+static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
+
+// Repeatedly makes Streaming Bidi calls (exchanging a configurable number of
+// messages in each call) in a loop on a single channel
+//
+// First parmeter (i.e state.range(0)): Message size (in bytes) to use
+// Second parameter (i.e state.range(1)): Number of ping pong messages.
+// Note: One ping-pong means two messages (one from client to server and
+// the other from server to client):
+template <class Fixture, class ClientContextMutator, class ServerContextMutator>
+static void BM_StreamingPingPong(benchmark::State& state) {
+ const int msg_size = state.range(0);
+ const int max_ping_pongs = state.range(1);
+
+ EchoTestService::AsyncService service;
+ std::unique_ptr<Fixture> fixture(new Fixture(&service));
+ {
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ EchoRequest send_request;
+ EchoRequest recv_request;
+
+ if (msg_size > 0) {
+ send_request.set_message(std::string(msg_size, 'a'));
+ send_response.set_message(std::string(msg_size, 'b'));
+ }
+
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+
+ while (state.KeepRunning()) {
+ ServerContext svr_ctx;
+ ServerContextMutator svr_ctx_mut(&svr_ctx);
+ ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+ service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+ fixture->cq(), tag(0));
+
+ ClientContext cli_ctx;
+ ClientContextMutator cli_ctx_mut(&cli_ctx);
+ auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+
+ // Establish async stream between client side and server side
+ void* t;
+ bool ok;
+ int need_tags = (1 << 0) | (1 << 1);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ // Send 'max_ping_pongs' number of ping pong messages
+ int ping_pong_cnt = 0;
+ while (ping_pong_cnt < max_ping_pongs) {
+ request_rw->Write(send_request, tag(0)); // Start client send
+ response_rw.Read(&recv_request, tag(1)); // Start server recv
+ request_rw->Read(&recv_response, tag(2)); // Start client recv
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+
+ // If server recv is complete, start the server send operation
+ if (i == 1) {
+ response_rw.Write(send_response, tag(3));
+ }
+
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ ping_pong_cnt++;
+ }
+
+ request_rw->WritesDone(tag(0));
+ response_rw.Finish(Status::OK, tag(1));
+
+ Status recv_status;
+ request_rw->Finish(&recv_status, tag(2));
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ GPR_ASSERT(recv_status.ok());
+ }
+ }
+
+ fixture->Finish(state);
+ fixture.reset();
+ state.SetBytesProcessed(msg_size * state.iterations() * max_ping_pongs * 2);
+}
+
+// Repeatedly sends ping pong messages in a single streaming Bidi call in a loop
+// First parmeter (i.e state.range(0)): Message size (in bytes) to use
+template <class Fixture, class ClientContextMutator, class ServerContextMutator>
+static void BM_StreamingPingPongMsgs(benchmark::State& state) {
+ const int msg_size = state.range(0);
+
+ EchoTestService::AsyncService service;
+ std::unique_ptr<Fixture> fixture(new Fixture(&service));
+ {
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ EchoRequest send_request;
+ EchoRequest recv_request;
+
+ if (msg_size > 0) {
+ send_request.set_message(std::string(msg_size, 'a'));
+ send_response.set_message(std::string(msg_size, 'b'));
+ }
+
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+
+ ServerContext svr_ctx;
+ ServerContextMutator svr_ctx_mut(&svr_ctx);
+ ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+ service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+ fixture->cq(), tag(0));
+
+ ClientContext cli_ctx;
+ ClientContextMutator cli_ctx_mut(&cli_ctx);
+ auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+
+ // Establish async stream between client side and server side
+ void* t;
+ bool ok;
+ int need_tags = (1 << 0) | (1 << 1);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ while (state.KeepRunning()) {
+ GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+ request_rw->Write(send_request, tag(0)); // Start client send
+ response_rw.Read(&recv_request, tag(1)); // Start server recv
+ request_rw->Read(&recv_response, tag(2)); // Start client recv
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+
+ // If server recv is complete, start the server send operation
+ if (i == 1) {
+ response_rw.Write(send_response, tag(3));
+ }
+
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ }
+
+ request_rw->WritesDone(tag(0));
+ response_rw.Finish(Status::OK, tag(1));
+ Status recv_status;
+ request_rw->Finish(&recv_status, tag(2));
+
+ need_tags = (1 << 0) | (1 << 1) | (1 << 2);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+
+ GPR_ASSERT(recv_status.ok());
+ }
+
+ fixture->Finish(state);
+ fixture.reset();
+ state.SetBytesProcessed(msg_size * state.iterations() * 2);
+}
+
+/*******************************************************************************
+ * CONFIGURATIONS
+ */
+
+// Generate Args for StreamingPingPong benchmarks. Currently generates args for
+// only "small streams" (i.e streams with 0, 1 or 2 messages)
+static void StreamingPingPongArgs(benchmark::internal::Benchmark* b) {
+ int msg_size = 0;
+
+ b->Args({0, 0}); // spl case: 0 ping-pong msgs (msg_size doesn't matter here)
+
+ for (msg_size = 0; msg_size <= 128 * 1024 * 1024;
+ msg_size == 0 ? msg_size++ : msg_size *= 8) {
+ b->Args({msg_size, 1});
+ b->Args({msg_size, 2});
+ }
+}
+
+BENCHMARK_TEMPLATE(BM_StreamingPingPong, InProcessCHTTP2, NoOpMutator,
+ NoOpMutator)
+ ->Apply(StreamingPingPongArgs);
+BENCHMARK_TEMPLATE(BM_StreamingPingPong, TCP, NoOpMutator, NoOpMutator)
+ ->Apply(StreamingPingPongArgs);
+
+BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, InProcessCHTTP2, NoOpMutator,
+ NoOpMutator)
+ ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_StreamingPingPongMsgs, TCP, NoOpMutator, NoOpMutator)
+ ->Range(0, 128 * 1024 * 1024);
+
+} // namespace testing
+} // namespace grpc
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
new file mode 100644
index 0000000000..dc0e7d769a
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_fullstack_streaming_pump.cc
@@ -0,0 +1,197 @@
+/*
+ *
+ * Copyright 2016, 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.
+ *
+ */
+
+/* Benchmark gRPC end2end in various configurations */
+
+#include <sstream>
+
+#include "src/core/lib/profiling/timers.h"
+#include "src/cpp/client/create_channel_internal.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
+#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+namespace grpc {
+namespace testing {
+
+// force library initialization
+auto& force_library_initialization = Library::get();
+
+/*******************************************************************************
+ * BENCHMARKING KERNELS
+ */
+
+static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
+
+template <class Fixture>
+static void BM_PumpStreamClientToServer(benchmark::State& state) {
+ EchoTestService::AsyncService service;
+ std::unique_ptr<Fixture> fixture(new Fixture(&service));
+ {
+ EchoRequest send_request;
+ EchoRequest recv_request;
+ if (state.range(0) > 0) {
+ send_request.set_message(std::string(state.range(0), 'a'));
+ }
+ Status recv_status;
+ ServerContext svr_ctx;
+ ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+ service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+ fixture->cq(), tag(0));
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+ ClientContext cli_ctx;
+ auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+ int need_tags = (1 << 0) | (1 << 1);
+ void* t;
+ bool ok;
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ response_rw.Read(&recv_request, tag(0));
+ while (state.KeepRunning()) {
+ GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+ request_rw->Write(send_request, tag(1));
+ while (true) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ if (t == tag(0)) {
+ response_rw.Read(&recv_request, tag(0));
+ } else if (t == tag(1)) {
+ break;
+ } else {
+ GPR_ASSERT(false);
+ }
+ }
+ }
+ request_rw->WritesDone(tag(1));
+ need_tags = (1 << 0) | (1 << 1);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ }
+ fixture->Finish(state);
+ fixture.reset();
+ state.SetBytesProcessed(state.range(0) * state.iterations());
+}
+
+template <class Fixture>
+static void BM_PumpStreamServerToClient(benchmark::State& state) {
+ EchoTestService::AsyncService service;
+ std::unique_ptr<Fixture> fixture(new Fixture(&service));
+ {
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ if (state.range(0) > 0) {
+ send_response.set_message(std::string(state.range(0), 'a'));
+ }
+ Status recv_status;
+ ServerContext svr_ctx;
+ ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+ service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+ fixture->cq(), tag(0));
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+ ClientContext cli_ctx;
+ auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+ int need_tags = (1 << 0) | (1 << 1);
+ void* t;
+ bool ok;
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ request_rw->Read(&recv_response, tag(0));
+ while (state.KeepRunning()) {
+ GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+ response_rw.Write(send_response, tag(1));
+ while (true) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ if (t == tag(0)) {
+ request_rw->Read(&recv_response, tag(0));
+ } else if (t == tag(1)) {
+ break;
+ } else {
+ GPR_ASSERT(false);
+ }
+ }
+ }
+ response_rw.Finish(Status::OK, tag(1));
+ need_tags = (1 << 0) | (1 << 1);
+ while (need_tags) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ }
+ fixture->Finish(state);
+ fixture.reset();
+ state.SetBytesProcessed(state.range(0) * state.iterations());
+}
+
+/*******************************************************************************
+ * CONFIGURATIONS
+ */
+
+BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, TCP)
+ ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, UDS)
+ ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, SockPair)
+ ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamClientToServer, InProcessCHTTP2)
+ ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, TCP)
+ ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, UDS)
+ ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, SockPair)
+ ->Range(0, 128 * 1024 * 1024);
+BENCHMARK_TEMPLATE(BM_PumpStreamServerToClient, InProcessCHTTP2)
+ ->Range(0, 128 * 1024 * 1024);
+
+} // namespace testing
+} // namespace grpc
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_fullstack_trickle.cc b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
new file mode 100644
index 0000000000..5011f06368
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_fullstack_trickle.cc
@@ -0,0 +1,219 @@
+/*
+ *
+ * Copyright 2016, 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.
+ *
+ */
+
+/* Benchmark gRPC end2end in various configurations */
+
+#include "src/core/lib/profiling/timers.h"
+#include "src/cpp/client/create_channel_internal.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
+#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+extern "C" {
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/ext/transport/chttp2/transport/internal.h"
+#include "test/core/util/trickle_endpoint.h"
+}
+
+namespace grpc {
+namespace testing {
+
+static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
+
+class TrickledCHTTP2 : public EndpointPairFixture {
+ public:
+ TrickledCHTTP2(Service* service, size_t megabits_per_second)
+ : EndpointPairFixture(service, MakeEndpoints(megabits_per_second)) {}
+
+ void AddToLabel(std::ostream& out, benchmark::State& state) {
+ out << " writes/iter:"
+ << ((double)stats_.num_writes / (double)state.iterations())
+ << " cli_transport_stalls/iter:"
+ << ((double)
+ client_stats_.streams_stalled_due_to_transport_flow_control /
+ (double)state.iterations())
+ << " cli_stream_stalls/iter:"
+ << ((double)client_stats_.streams_stalled_due_to_stream_flow_control /
+ (double)state.iterations())
+ << " svr_transport_stalls/iter:"
+ << ((double)
+ server_stats_.streams_stalled_due_to_transport_flow_control /
+ (double)state.iterations())
+ << " svr_stream_stalls/iter:"
+ << ((double)server_stats_.streams_stalled_due_to_stream_flow_control /
+ (double)state.iterations());
+ }
+
+ void Step() {
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ size_t client_backlog =
+ grpc_trickle_endpoint_trickle(&exec_ctx, endpoint_pair_.client);
+ size_t server_backlog =
+ grpc_trickle_endpoint_trickle(&exec_ctx, endpoint_pair_.server);
+ grpc_exec_ctx_finish(&exec_ctx);
+
+ UpdateStats((grpc_chttp2_transport*)client_transport_, &client_stats_,
+ client_backlog);
+ UpdateStats((grpc_chttp2_transport*)server_transport_, &server_stats_,
+ server_backlog);
+ }
+
+ private:
+ grpc_passthru_endpoint_stats stats_;
+ struct Stats {
+ int streams_stalled_due_to_stream_flow_control = 0;
+ int streams_stalled_due_to_transport_flow_control = 0;
+ };
+ Stats client_stats_;
+ Stats server_stats_;
+
+ grpc_endpoint_pair MakeEndpoints(size_t kilobits) {
+ grpc_endpoint_pair p;
+ grpc_passthru_endpoint_create(&p.client, &p.server, Library::get().rq(),
+ &stats_);
+ double bytes_per_second = 125.0 * kilobits;
+ p.client = grpc_trickle_endpoint_create(p.client, bytes_per_second);
+ p.server = grpc_trickle_endpoint_create(p.server, bytes_per_second);
+ return p;
+ }
+
+ void UpdateStats(grpc_chttp2_transport* t, Stats* s, size_t backlog) {
+ if (backlog == 0) {
+ if (t->lists[GRPC_CHTTP2_LIST_STALLED_BY_STREAM].head != NULL) {
+ s->streams_stalled_due_to_stream_flow_control++;
+ }
+ if (t->lists[GRPC_CHTTP2_LIST_STALLED_BY_TRANSPORT].head != NULL) {
+ s->streams_stalled_due_to_transport_flow_control++;
+ }
+ }
+ }
+};
+
+// force library initialization
+auto& force_library_initialization = Library::get();
+
+static void TrickleCQNext(TrickledCHTTP2* fixture, void** t, bool* ok) {
+ while (true) {
+ switch (fixture->cq()->AsyncNext(
+ t, ok, gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+ gpr_time_from_micros(100, GPR_TIMESPAN)))) {
+ case CompletionQueue::TIMEOUT:
+ fixture->Step();
+ break;
+ case CompletionQueue::SHUTDOWN:
+ GPR_ASSERT(false);
+ break;
+ case CompletionQueue::GOT_EVENT:
+ return;
+ }
+ }
+}
+
+static void BM_PumpStreamServerToClient_Trickle(benchmark::State& state) {
+ EchoTestService::AsyncService service;
+ std::unique_ptr<TrickledCHTTP2> fixture(
+ new TrickledCHTTP2(&service, state.range(1)));
+ {
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ if (state.range(0) > 0) {
+ send_response.set_message(std::string(state.range(0), 'a'));
+ }
+ Status recv_status;
+ ServerContext svr_ctx;
+ ServerAsyncReaderWriter<EchoResponse, EchoRequest> response_rw(&svr_ctx);
+ service.RequestBidiStream(&svr_ctx, &response_rw, fixture->cq(),
+ fixture->cq(), tag(0));
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+ ClientContext cli_ctx;
+ auto request_rw = stub->AsyncBidiStream(&cli_ctx, fixture->cq(), tag(1));
+ int need_tags = (1 << 0) | (1 << 1);
+ void* t;
+ bool ok;
+ while (need_tags) {
+ TrickleCQNext(fixture.get(), &t, &ok);
+ GPR_ASSERT(ok);
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ request_rw->Read(&recv_response, tag(0));
+ while (state.KeepRunning()) {
+ GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+ response_rw.Write(send_response, tag(1));
+ while (true) {
+ TrickleCQNext(fixture.get(), &t, &ok);
+ if (t == tag(0)) {
+ request_rw->Read(&recv_response, tag(0));
+ } else if (t == tag(1)) {
+ break;
+ } else {
+ GPR_ASSERT(false);
+ }
+ }
+ }
+ response_rw.Finish(Status::OK, tag(1));
+ need_tags = (1 << 0) | (1 << 1);
+ while (need_tags) {
+ TrickleCQNext(fixture.get(), &t, &ok);
+ int i = (int)(intptr_t)t;
+ GPR_ASSERT(need_tags & (1 << i));
+ need_tags &= ~(1 << i);
+ }
+ }
+ fixture->Finish(state);
+ fixture.reset();
+ state.SetBytesProcessed(state.range(0) * state.iterations());
+}
+
+/*******************************************************************************
+ * CONFIGURATIONS
+ */
+
+static void TrickleArgs(benchmark::internal::Benchmark* b) {
+ for (int i = 1; i <= 128 * 1024 * 1024; i *= 8) {
+ for (int j = 1; j <= 128 * 1024 * 1024; j *= 8) {
+ double expected_time =
+ static_cast<double>(14 + i) / (125.0 * static_cast<double>(j));
+ if (expected_time > 0.01) continue;
+ b->Args({i, j});
+ }
+ }
+}
+
+BENCHMARK(BM_PumpStreamServerToClient_Trickle)->Apply(TrickleArgs);
+}
+}
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
new file mode 100644
index 0000000000..e51d272b10
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_fullstack_unary_ping_pong.cc
@@ -0,0 +1,205 @@
+/*
+ *
+ * Copyright 2016, 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.
+ *
+ */
+
+/* Benchmark gRPC end2end in various configurations */
+
+#include <sstream>
+
+#include "src/core/lib/profiling/timers.h"
+#include "src/cpp/client/create_channel_internal.h"
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/cpp/microbenchmarks/fullstack_context_mutators.h"
+#include "test/cpp/microbenchmarks/fullstack_fixtures.h"
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+namespace grpc {
+namespace testing {
+
+// force library initialization
+auto& force_library_initialization = Library::get();
+
+/*******************************************************************************
+ * BENCHMARKING KERNELS
+ */
+
+static void* tag(intptr_t x) { return reinterpret_cast<void*>(x); }
+
+template <class Fixture, class ClientContextMutator, class ServerContextMutator>
+static void BM_UnaryPingPong(benchmark::State& state) {
+ EchoTestService::AsyncService service;
+ std::unique_ptr<Fixture> fixture(new Fixture(&service));
+ EchoRequest send_request;
+ EchoResponse send_response;
+ EchoResponse recv_response;
+ if (state.range(0) > 0) {
+ send_request.set_message(std::string(state.range(0), 'a'));
+ }
+ if (state.range(1) > 0) {
+ send_response.set_message(std::string(state.range(1), 'a'));
+ }
+ Status recv_status;
+ struct ServerEnv {
+ ServerContext ctx;
+ EchoRequest recv_request;
+ grpc::ServerAsyncResponseWriter<EchoResponse> response_writer;
+ ServerEnv() : response_writer(&ctx) {}
+ };
+ uint8_t server_env_buffer[2 * sizeof(ServerEnv)];
+ ServerEnv* server_env[2] = {
+ reinterpret_cast<ServerEnv*>(server_env_buffer),
+ reinterpret_cast<ServerEnv*>(server_env_buffer + sizeof(ServerEnv))};
+ new (server_env[0]) ServerEnv;
+ new (server_env[1]) ServerEnv;
+ service.RequestEcho(&server_env[0]->ctx, &server_env[0]->recv_request,
+ &server_env[0]->response_writer, fixture->cq(),
+ fixture->cq(), tag(0));
+ service.RequestEcho(&server_env[1]->ctx, &server_env[1]->recv_request,
+ &server_env[1]->response_writer, fixture->cq(),
+ fixture->cq(), tag(1));
+ std::unique_ptr<EchoTestService::Stub> stub(
+ EchoTestService::NewStub(fixture->channel()));
+ while (state.KeepRunning()) {
+ GPR_TIMER_SCOPE("BenchmarkCycle", 0);
+ recv_response.Clear();
+ ClientContext cli_ctx;
+ ClientContextMutator cli_ctx_mut(&cli_ctx);
+ std::unique_ptr<ClientAsyncResponseReader<EchoResponse>> response_reader(
+ stub->AsyncEcho(&cli_ctx, send_request, fixture->cq()));
+ void* t;
+ bool ok;
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ GPR_ASSERT(t == tag(0) || t == tag(1));
+ intptr_t slot = reinterpret_cast<intptr_t>(t);
+ ServerEnv* senv = server_env[slot];
+ ServerContextMutator svr_ctx_mut(&senv->ctx);
+ senv->response_writer.Finish(send_response, Status::OK, tag(3));
+ response_reader->Finish(&recv_response, &recv_status, tag(4));
+ for (int i = (1 << 3) | (1 << 4); i != 0;) {
+ GPR_ASSERT(fixture->cq()->Next(&t, &ok));
+ GPR_ASSERT(ok);
+ int tagnum = (int)reinterpret_cast<intptr_t>(t);
+ GPR_ASSERT(i & (1 << tagnum));
+ i -= 1 << tagnum;
+ }
+ GPR_ASSERT(recv_status.ok());
+
+ senv->~ServerEnv();
+ senv = new (senv) ServerEnv();
+ service.RequestEcho(&senv->ctx, &senv->recv_request, &senv->response_writer,
+ fixture->cq(), fixture->cq(), tag(slot));
+ }
+ fixture->Finish(state);
+ fixture.reset();
+ server_env[0]->~ServerEnv();
+ server_env[1]->~ServerEnv();
+ state.SetBytesProcessed(state.range(0) * state.iterations() +
+ state.range(1) * state.iterations());
+}
+
+/*******************************************************************************
+ * CONFIGURATIONS
+ */
+
+static void SweepSizesArgs(benchmark::internal::Benchmark* b) {
+ b->Args({0, 0});
+ for (int i = 1; i <= 128 * 1024 * 1024; i *= 8) {
+ b->Args({i, 0});
+ b->Args({0, i});
+ b->Args({i, i});
+ }
+}
+
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, TCP, NoOpMutator, NoOpMutator)
+ ->Apply(SweepSizesArgs);
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, UDS, NoOpMutator, NoOpMutator)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, SockPair, NoOpMutator, NoOpMutator)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator, NoOpMutator)
+ ->Apply(SweepSizesArgs);
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
+ Client_AddMetadata<RandomBinaryMetadata<10>, 1>, NoOpMutator)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
+ Client_AddMetadata<RandomBinaryMetadata<31>, 1>, NoOpMutator)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
+ Client_AddMetadata<RandomBinaryMetadata<100>, 1>,
+ NoOpMutator)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
+ Client_AddMetadata<RandomBinaryMetadata<10>, 2>, NoOpMutator)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
+ Client_AddMetadata<RandomBinaryMetadata<31>, 2>, NoOpMutator)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
+ Client_AddMetadata<RandomBinaryMetadata<100>, 2>,
+ NoOpMutator)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
+ Server_AddInitialMetadata<RandomBinaryMetadata<10>, 1>)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
+ Server_AddInitialMetadata<RandomBinaryMetadata<31>, 1>)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
+ Server_AddInitialMetadata<RandomBinaryMetadata<100>, 1>)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
+ Client_AddMetadata<RandomAsciiMetadata<10>, 1>, NoOpMutator)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
+ Client_AddMetadata<RandomAsciiMetadata<31>, 1>, NoOpMutator)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2,
+ Client_AddMetadata<RandomAsciiMetadata<100>, 1>, NoOpMutator)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
+ Server_AddInitialMetadata<RandomAsciiMetadata<10>, 1>)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
+ Server_AddInitialMetadata<RandomAsciiMetadata<31>, 1>)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
+ Server_AddInitialMetadata<RandomAsciiMetadata<100>, 1>)
+ ->Args({0, 0});
+BENCHMARK_TEMPLATE(BM_UnaryPingPong, InProcessCHTTP2, NoOpMutator,
+ Server_AddInitialMetadata<RandomAsciiMetadata<10>, 100>)
+ ->Args({0, 0});
+
+} // namespace testing
+} // namespace grpc
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/bm_metadata.cc b/test/cpp/microbenchmarks/bm_metadata.cc
index 7f81fbabcc..34874b57f5 100644
--- a/test/cpp/microbenchmarks/bm_metadata.cc
+++ b/test/cpp/microbenchmarks/bm_metadata.cc
@@ -1,6 +1,6 @@
/*
*
- * Copyright 2015, Google Inc.
+ * Copyright 2017, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,65 +36,90 @@
#include <grpc/grpc.h>
extern "C" {
+#include "src/core/lib/slice/slice_internal.h"
#include "src/core/lib/transport/metadata.h"
#include "src/core/lib/transport/static_metadata.h"
+#include "src/core/lib/transport/transport.h"
}
+#include "test/cpp/microbenchmarks/helpers.h"
#include "third_party/benchmark/include/benchmark/benchmark.h"
-static class InitializeStuff {
- public:
- InitializeStuff() { grpc_init(); }
- ~InitializeStuff() { grpc_shutdown(); }
-} initialize_stuff;
+auto& force_library_initialization = Library::get();
static void BM_SliceFromStatic(benchmark::State& state) {
+ TrackCounters track_counters;
while (state.KeepRunning()) {
benchmark::DoNotOptimize(grpc_slice_from_static_string("abc"));
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_SliceFromStatic);
static void BM_SliceFromCopied(benchmark::State& state) {
+ TrackCounters track_counters;
while (state.KeepRunning()) {
grpc_slice_unref(grpc_slice_from_copied_string("abc"));
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_SliceFromCopied);
+static void BM_SliceFromStreamOwnedBuffer(benchmark::State& state) {
+ grpc_stream_refcount r;
+ GRPC_STREAM_REF_INIT(&r, 1, NULL, NULL, "test");
+ char buffer[64];
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ while (state.KeepRunning()) {
+ grpc_slice_unref_internal(&exec_ctx, grpc_slice_from_stream_owned_buffer(
+ &r, buffer, sizeof(buffer)));
+ }
+ grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_SliceFromStreamOwnedBuffer);
+
static void BM_SliceIntern(benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice slice = grpc_slice_from_static_string("abc");
while (state.KeepRunning()) {
grpc_slice_unref(grpc_slice_intern(slice));
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_SliceIntern);
static void BM_SliceReIntern(benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice slice = grpc_slice_intern(grpc_slice_from_static_string("abc"));
while (state.KeepRunning()) {
grpc_slice_unref(grpc_slice_intern(slice));
}
grpc_slice_unref(slice);
+ track_counters.Finish(state);
}
BENCHMARK(BM_SliceReIntern);
static void BM_SliceInternStaticMetadata(benchmark::State& state) {
+ TrackCounters track_counters;
while (state.KeepRunning()) {
grpc_slice_intern(GRPC_MDSTR_GZIP);
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_SliceInternStaticMetadata);
static void BM_SliceInternEqualToStaticMetadata(benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice slice = grpc_slice_from_static_string("gzip");
while (state.KeepRunning()) {
grpc_slice_intern(slice);
}
+ track_counters.Finish(state);
}
BENCHMARK(BM_SliceInternEqualToStaticMetadata);
static void BM_MetadataFromNonInternedSlices(benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice k = grpc_slice_from_static_string("key");
gpr_slice v = grpc_slice_from_static_string("value");
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -102,10 +127,12 @@ static void BM_MetadataFromNonInternedSlices(benchmark::State& state) {
GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromNonInternedSlices);
static void BM_MetadataFromInternedSlices(benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value"));
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -115,11 +142,13 @@ static void BM_MetadataFromInternedSlices(benchmark::State& state) {
grpc_exec_ctx_finish(&exec_ctx);
grpc_slice_unref(k);
grpc_slice_unref(v);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedSlices);
static void BM_MetadataFromInternedSlicesAlreadyInIndex(
benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value"));
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -131,10 +160,12 @@ static void BM_MetadataFromInternedSlicesAlreadyInIndex(
grpc_exec_ctx_finish(&exec_ctx);
grpc_slice_unref(k);
grpc_slice_unref(v);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedSlicesAlreadyInIndex);
static void BM_MetadataFromInternedKey(benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
gpr_slice v = grpc_slice_from_static_string("value");
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -143,11 +174,13 @@ static void BM_MetadataFromInternedKey(benchmark::State& state) {
}
grpc_exec_ctx_finish(&exec_ctx);
grpc_slice_unref(k);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedKey);
static void BM_MetadataFromNonInternedSlicesWithBackingStore(
benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice k = grpc_slice_from_static_string("key");
gpr_slice v = grpc_slice_from_static_string("value");
char backing_store[sizeof(grpc_mdelem_data)];
@@ -159,11 +192,13 @@ static void BM_MetadataFromNonInternedSlicesWithBackingStore(
reinterpret_cast<grpc_mdelem_data*>(backing_store)));
}
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromNonInternedSlicesWithBackingStore);
static void BM_MetadataFromInternedSlicesWithBackingStore(
benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value"));
char backing_store[sizeof(grpc_mdelem_data)];
@@ -177,11 +212,13 @@ static void BM_MetadataFromInternedSlicesWithBackingStore(
grpc_exec_ctx_finish(&exec_ctx);
grpc_slice_unref(k);
grpc_slice_unref(v);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedSlicesWithBackingStore);
static void BM_MetadataFromInternedKeyWithBackingStore(
benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
gpr_slice v = grpc_slice_from_static_string("value");
char backing_store[sizeof(grpc_mdelem_data)];
@@ -194,10 +231,12 @@ static void BM_MetadataFromInternedKeyWithBackingStore(
}
grpc_exec_ctx_finish(&exec_ctx);
grpc_slice_unref(k);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromInternedKeyWithBackingStore);
static void BM_MetadataFromStaticMetadataStrings(benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice k = GRPC_MDSTR_STATUS;
gpr_slice v = GRPC_MDSTR_200;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -206,11 +245,13 @@ static void BM_MetadataFromStaticMetadataStrings(benchmark::State& state) {
}
grpc_exec_ctx_finish(&exec_ctx);
grpc_slice_unref(k);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromStaticMetadataStrings);
static void BM_MetadataFromStaticMetadataStringsNotIndexed(
benchmark::State& state) {
+ TrackCounters track_counters;
gpr_slice k = GRPC_MDSTR_STATUS;
gpr_slice v = GRPC_MDSTR_GZIP;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
@@ -219,10 +260,12 @@ static void BM_MetadataFromStaticMetadataStringsNotIndexed(
}
grpc_exec_ctx_finish(&exec_ctx);
grpc_slice_unref(k);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataFromStaticMetadataStringsNotIndexed);
static void BM_MetadataRefUnrefExternal(benchmark::State& state) {
+ TrackCounters track_counters;
char backing_store[sizeof(grpc_mdelem_data)];
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_mdelem el =
@@ -234,10 +277,12 @@ static void BM_MetadataRefUnrefExternal(benchmark::State& state) {
}
GRPC_MDELEM_UNREF(&exec_ctx, el);
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefExternal);
static void BM_MetadataRefUnrefInterned(benchmark::State& state) {
+ TrackCounters track_counters;
char backing_store[sizeof(grpc_mdelem_data)];
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
@@ -251,10 +296,12 @@ static void BM_MetadataRefUnrefInterned(benchmark::State& state) {
}
GRPC_MDELEM_UNREF(&exec_ctx, el);
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefInterned);
static void BM_MetadataRefUnrefAllocated(benchmark::State& state) {
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_mdelem el =
grpc_mdelem_create(&exec_ctx, grpc_slice_from_static_string("a"),
@@ -264,10 +311,12 @@ static void BM_MetadataRefUnrefAllocated(benchmark::State& state) {
}
GRPC_MDELEM_UNREF(&exec_ctx, el);
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefAllocated);
static void BM_MetadataRefUnrefStatic(benchmark::State& state) {
+ TrackCounters track_counters;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_mdelem el =
grpc_mdelem_create(&exec_ctx, GRPC_MDSTR_STATUS, GRPC_MDSTR_200, NULL);
@@ -276,6 +325,7 @@ static void BM_MetadataRefUnrefStatic(benchmark::State& state) {
}
GRPC_MDELEM_UNREF(&exec_ctx, el);
grpc_exec_ctx_finish(&exec_ctx);
+ track_counters.Finish(state);
}
BENCHMARK(BM_MetadataRefUnrefStatic);
diff --git a/test/cpp/microbenchmarks/bm_pollset.cc b/test/cpp/microbenchmarks/bm_pollset.cc
new file mode 100644
index 0000000000..0f3d3cef66
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_pollset.cc
@@ -0,0 +1,254 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* Test out pollset latencies */
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/useful.h>
+
+extern "C" {
+#include "src/core/lib/iomgr/ev_posix.h"
+#include "src/core/lib/iomgr/pollset.h"
+#include "src/core/lib/iomgr/port.h"
+#include "src/core/lib/iomgr/wakeup_fd_posix.h"
+}
+
+#include "test/cpp/microbenchmarks/helpers.h"
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+#include <string.h>
+
+#ifdef GRPC_LINUX_MULTIPOLL_WITH_EPOLL
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+#include <unistd.h>
+#endif
+
+auto& force_library_initialization = Library::get();
+
+static void shutdown_ps(grpc_exec_ctx* exec_ctx, void* ps, grpc_error* error) {
+ grpc_pollset_destroy(static_cast<grpc_pollset*>(ps));
+}
+
+static void BM_CreateDestroyPollset(benchmark::State& state) {
+ TrackCounters track_counters;
+ size_t ps_sz = grpc_pollset_size();
+ grpc_pollset* ps = static_cast<grpc_pollset*>(gpr_malloc(ps_sz));
+ gpr_mu* mu;
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ grpc_closure shutdown_ps_closure;
+ grpc_closure_init(&shutdown_ps_closure, shutdown_ps, ps,
+ grpc_schedule_on_exec_ctx);
+ while (state.KeepRunning()) {
+ memset(ps, 0, ps_sz);
+ grpc_pollset_init(ps, &mu);
+ gpr_mu_lock(mu);
+ grpc_pollset_shutdown(&exec_ctx, ps, &shutdown_ps_closure);
+ gpr_mu_unlock(mu);
+ grpc_exec_ctx_flush(&exec_ctx);
+ }
+ grpc_exec_ctx_finish(&exec_ctx);
+ gpr_free(ps);
+ track_counters.Finish(state);
+}
+BENCHMARK(BM_CreateDestroyPollset);
+
+#ifdef GRPC_LINUX_MULTIPOLL_WITH_EPOLL
+static void BM_PollEmptyPollset_SpeedOfLight(benchmark::State& state) {
+ // equivalent to BM_PollEmptyPollset, but just use the OS primitives to guage
+ // what the speed of light would be if we abstracted perfectly
+ TrackCounters track_counters;
+ int epfd = epoll_create1(0);
+ GPR_ASSERT(epfd != -1);
+ size_t nev = state.range(0);
+ size_t nfd = state.range(1);
+ epoll_event* ev = new epoll_event[nev];
+ std::vector<int> fds;
+ for (size_t i = 0; i < nfd; i++) {
+ fds.push_back(eventfd(0, 0));
+ epoll_event ev;
+ ev.events = EPOLLIN;
+ epoll_ctl(epfd, EPOLL_CTL_ADD, fds.back(), &ev);
+ }
+ while (state.KeepRunning()) {
+ epoll_wait(epfd, ev, nev, 0);
+ }
+ for (auto fd : fds) {
+ close(fd);
+ }
+ close(epfd);
+ delete[] ev;
+ track_counters.Finish(state);
+}
+BENCHMARK(BM_PollEmptyPollset_SpeedOfLight)
+ ->Args({1, 0})
+ ->Args({1, 1})
+ ->Args({1, 10})
+ ->Args({1, 100})
+ ->Args({1, 1000})
+ ->Args({1, 10000})
+ ->Args({1, 100000})
+ ->Args({10, 1})
+ ->Args({100, 1})
+ ->Args({1000, 1});
+#endif
+
+static void BM_PollEmptyPollset(benchmark::State& state) {
+ TrackCounters track_counters;
+ size_t ps_sz = grpc_pollset_size();
+ grpc_pollset* ps = static_cast<grpc_pollset*>(gpr_zalloc(ps_sz));
+ gpr_mu* mu;
+ grpc_pollset_init(ps, &mu);
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ gpr_timespec now = gpr_time_0(GPR_CLOCK_MONOTONIC);
+ gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
+ gpr_mu_lock(mu);
+ while (state.KeepRunning()) {
+ grpc_pollset_worker* worker;
+ GRPC_ERROR_UNREF(grpc_pollset_work(&exec_ctx, ps, &worker, now, deadline));
+ }
+ grpc_closure shutdown_ps_closure;
+ grpc_closure_init(&shutdown_ps_closure, shutdown_ps, ps,
+ grpc_schedule_on_exec_ctx);
+ grpc_pollset_shutdown(&exec_ctx, ps, &shutdown_ps_closure);
+ gpr_mu_unlock(mu);
+ grpc_exec_ctx_finish(&exec_ctx);
+ gpr_free(ps);
+ track_counters.Finish(state);
+}
+BENCHMARK(BM_PollEmptyPollset);
+
+class Closure : public grpc_closure {
+ public:
+ virtual ~Closure() {}
+};
+
+template <class F>
+Closure* MakeClosure(F f, grpc_closure_scheduler* scheduler) {
+ struct C : public Closure {
+ C(F f, grpc_closure_scheduler* scheduler) : f_(f) {
+ grpc_closure_init(this, C::cbfn, this, scheduler);
+ }
+ static void cbfn(grpc_exec_ctx* exec_ctx, void* arg, grpc_error* error) {
+ C* p = static_cast<C*>(arg);
+ p->f_();
+ }
+ F f_;
+ };
+ return new C(f, scheduler);
+}
+
+#ifdef GRPC_LINUX_MULTIPOLL_WITH_EPOLL
+static void BM_SingleThreadPollOneFd_SpeedOfLight(benchmark::State& state) {
+ // equivalent to BM_PollEmptyPollset, but just use the OS primitives to guage
+ // what the speed of light would be if we abstracted perfectly
+ TrackCounters track_counters;
+ int epfd = epoll_create1(0);
+ GPR_ASSERT(epfd != -1);
+ epoll_event ev[100];
+ int fd = eventfd(0, EFD_NONBLOCK);
+ ev[0].events = EPOLLIN;
+ epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev[0]);
+ while (state.KeepRunning()) {
+ int err;
+ do {
+ err = eventfd_write(fd, 1);
+ } while (err < 0 && errno == EINTR);
+ GPR_ASSERT(err == 0);
+ do {
+ err = epoll_wait(epfd, ev, GPR_ARRAY_SIZE(ev), 0);
+ } while (err < 0 && errno == EINTR);
+ GPR_ASSERT(err == 1);
+ eventfd_t value;
+ do {
+ err = eventfd_read(fd, &value);
+ } while (err < 0 && errno == EINTR);
+ GPR_ASSERT(err == 0);
+ }
+ close(fd);
+ close(epfd);
+ track_counters.Finish(state);
+}
+BENCHMARK(BM_SingleThreadPollOneFd_SpeedOfLight);
+#endif
+
+static void BM_SingleThreadPollOneFd(benchmark::State& state) {
+ TrackCounters track_counters;
+ size_t ps_sz = grpc_pollset_size();
+ grpc_pollset* ps = static_cast<grpc_pollset*>(gpr_zalloc(ps_sz));
+ gpr_mu* mu;
+ grpc_pollset_init(ps, &mu);
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ gpr_timespec now = gpr_time_0(GPR_CLOCK_MONOTONIC);
+ gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
+ grpc_wakeup_fd wakeup_fd;
+ GRPC_ERROR_UNREF(grpc_wakeup_fd_init(&wakeup_fd));
+ grpc_fd* wakeup = grpc_fd_create(wakeup_fd.read_fd, "wakeup_read");
+ grpc_pollset_add_fd(&exec_ctx, ps, wakeup);
+ bool done = false;
+ Closure* continue_closure = MakeClosure(
+ [&]() {
+ GRPC_ERROR_UNREF(grpc_wakeup_fd_consume_wakeup(&wakeup_fd));
+ if (!state.KeepRunning()) {
+ done = true;
+ return;
+ }
+ GRPC_ERROR_UNREF(grpc_wakeup_fd_wakeup(&wakeup_fd));
+ grpc_fd_notify_on_read(&exec_ctx, wakeup, continue_closure);
+ },
+ grpc_schedule_on_exec_ctx);
+ GRPC_ERROR_UNREF(grpc_wakeup_fd_wakeup(&wakeup_fd));
+ grpc_fd_notify_on_read(&exec_ctx, wakeup, continue_closure);
+ gpr_mu_lock(mu);
+ while (!done) {
+ grpc_pollset_worker* worker;
+ GRPC_ERROR_UNREF(grpc_pollset_work(&exec_ctx, ps, &worker, now, deadline));
+ }
+ grpc_fd_orphan(&exec_ctx, wakeup, NULL, NULL, "done");
+ wakeup_fd.read_fd = 0;
+ grpc_closure shutdown_ps_closure;
+ grpc_closure_init(&shutdown_ps_closure, shutdown_ps, ps,
+ grpc_schedule_on_exec_ctx);
+ grpc_pollset_shutdown(&exec_ctx, ps, &shutdown_ps_closure);
+ gpr_mu_unlock(mu);
+ grpc_exec_ctx_finish(&exec_ctx);
+ grpc_wakeup_fd_destroy(&wakeup_fd);
+ gpr_free(ps);
+ track_counters.Finish(state);
+ delete continue_closure;
+}
+BENCHMARK(BM_SingleThreadPollOneFd);
+
+BENCHMARK_MAIN();
diff --git a/test/cpp/microbenchmarks/fullstack_context_mutators.h b/test/cpp/microbenchmarks/fullstack_context_mutators.h
new file mode 100644
index 0000000000..676f9aa1cc
--- /dev/null
+++ b/test/cpp/microbenchmarks/fullstack_context_mutators.h
@@ -0,0 +1,158 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef TEST_CPP_MICROBENCHMARKS_FULLSTACK_CONTEXT_MUTATORS_H
+#define TEST_CPP_MICROBENCHMARKS_FULLSTACK_CONTEXT_MUTATORS_H
+
+#include <grpc++/channel.h>
+#include <grpc++/create_channel.h>
+#include <grpc++/security/credentials.h>
+#include <grpc++/security/server_credentials.h>
+#include <grpc++/server.h>
+#include <grpc++/server_builder.h>
+#include <grpc++/server_context.h>
+#include <grpc/support/log.h>
+
+#include "test/cpp/microbenchmarks/helpers.h"
+
+namespace grpc {
+namespace testing {
+
+/*******************************************************************************
+ * CONTEXT MUTATORS
+ */
+
+static const int kPregenerateKeyCount = 100000;
+
+template <class F>
+auto MakeVector(size_t length, F f) -> std::vector<decltype(f())> {
+ std::vector<decltype(f())> out;
+ out.reserve(length);
+ for (size_t i = 0; i < length; i++) {
+ out.push_back(f());
+ }
+ return out;
+}
+
+class NoOpMutator {
+ public:
+ template <class ContextType>
+ NoOpMutator(ContextType* context) {}
+};
+
+template <int length>
+class RandomBinaryMetadata {
+ public:
+ static const grpc::string& Key() { return kKey; }
+
+ static const grpc::string& Value() {
+ return kValues[rand() % kValues.size()];
+ }
+
+ private:
+ static const grpc::string kKey;
+ static const std::vector<grpc::string> kValues;
+
+ static grpc::string GenerateOneString() {
+ grpc::string s;
+ s.reserve(length + 1);
+ for (int i = 0; i < length; i++) {
+ s += (char)rand();
+ }
+ return s;
+ }
+};
+
+template <int length>
+class RandomAsciiMetadata {
+ public:
+ static const grpc::string& Key() { return kKey; }
+
+ static const grpc::string& Value() {
+ return kValues[rand() % kValues.size()];
+ }
+
+ private:
+ static const grpc::string kKey;
+ static const std::vector<grpc::string> kValues;
+
+ static grpc::string GenerateOneString() {
+ grpc::string s;
+ s.reserve(length + 1);
+ for (int i = 0; i < length; i++) {
+ s += (char)(rand() % 26 + 'a');
+ }
+ return s;
+ }
+};
+
+template <class Generator, int kNumKeys>
+class Client_AddMetadata : public NoOpMutator {
+ public:
+ Client_AddMetadata(ClientContext* context) : NoOpMutator(context) {
+ for (int i = 0; i < kNumKeys; i++) {
+ context->AddMetadata(Generator::Key(), Generator::Value());
+ }
+ }
+};
+
+template <class Generator, int kNumKeys>
+class Server_AddInitialMetadata : public NoOpMutator {
+ public:
+ Server_AddInitialMetadata(ServerContext* context) : NoOpMutator(context) {
+ for (int i = 0; i < kNumKeys; i++) {
+ context->AddInitialMetadata(Generator::Key(), Generator::Value());
+ }
+ }
+};
+
+// static initialization
+
+template <int length>
+const grpc::string RandomBinaryMetadata<length>::kKey = "foo-bin";
+
+template <int length>
+const std::vector<grpc::string> RandomBinaryMetadata<length>::kValues =
+ MakeVector(kPregenerateKeyCount, GenerateOneString);
+
+template <int length>
+const grpc::string RandomAsciiMetadata<length>::kKey = "foo";
+
+template <int length>
+const std::vector<grpc::string> RandomAsciiMetadata<length>::kValues =
+ MakeVector(kPregenerateKeyCount, GenerateOneString);
+
+} // namespace testing
+} // namespace grpc
+
+#endif
diff --git a/test/cpp/microbenchmarks/fullstack_fixtures.h b/test/cpp/microbenchmarks/fullstack_fixtures.h
new file mode 100644
index 0000000000..dc29701059
--- /dev/null
+++ b/test/cpp/microbenchmarks/fullstack_fixtures.h
@@ -0,0 +1,244 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef TEST_CPP_MICROBENCHMARKS_FULLSTACK_FIXTURES_H
+#define TEST_CPP_MICROBENCHMARKS_FULLSTACK_FIXTURES_H
+
+#include <grpc++/channel.h>
+#include <grpc++/create_channel.h>
+#include <grpc++/security/credentials.h>
+#include <grpc++/security/server_credentials.h>
+#include <grpc++/server.h>
+#include <grpc++/server_builder.h>
+#include <grpc/support/log.h>
+
+extern "C" {
+#include "src/core/ext/transport/chttp2/transport/chttp2_transport.h"
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/endpoint.h"
+#include "src/core/lib/iomgr/endpoint_pair.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/tcp_posix.h"
+#include "src/core/lib/surface/channel.h"
+#include "src/core/lib/surface/completion_queue.h"
+#include "src/core/lib/surface/server.h"
+#include "test/core/util/passthru_endpoint.h"
+#include "test/core/util/port.h"
+}
+
+#include "test/cpp/microbenchmarks/helpers.h"
+
+namespace grpc {
+namespace testing {
+
+static void ApplyCommonServerBuilderConfig(ServerBuilder* b) {
+ b->SetMaxReceiveMessageSize(INT_MAX);
+ b->SetMaxSendMessageSize(INT_MAX);
+}
+
+static void ApplyCommonChannelArguments(ChannelArguments* c) {
+ c->SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, INT_MAX);
+ c->SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, INT_MAX);
+}
+
+class BaseFixture : public TrackCounters {};
+
+class FullstackFixture : public BaseFixture {
+ public:
+ FullstackFixture(Service* service, const grpc::string& address) {
+ ServerBuilder b;
+ b.AddListeningPort(address, InsecureServerCredentials());
+ cq_ = b.AddCompletionQueue(true);
+ b.RegisterService(service);
+ ApplyCommonServerBuilderConfig(&b);
+ server_ = b.BuildAndStart();
+ ChannelArguments args;
+ ApplyCommonChannelArguments(&args);
+ channel_ = CreateCustomChannel(address, InsecureChannelCredentials(), args);
+ }
+
+ virtual ~FullstackFixture() {
+ server_->Shutdown();
+ cq_->Shutdown();
+ void* tag;
+ bool ok;
+ while (cq_->Next(&tag, &ok)) {
+ }
+ }
+
+ ServerCompletionQueue* cq() { return cq_.get(); }
+ std::shared_ptr<Channel> channel() { return channel_; }
+
+ private:
+ std::unique_ptr<Server> server_;
+ std::unique_ptr<ServerCompletionQueue> cq_;
+ std::shared_ptr<Channel> channel_;
+};
+
+class TCP : public FullstackFixture {
+ public:
+ TCP(Service* service) : FullstackFixture(service, MakeAddress()) {}
+
+ private:
+ static grpc::string MakeAddress() {
+ int port = grpc_pick_unused_port_or_die();
+ std::stringstream addr;
+ addr << "localhost:" << port;
+ return addr.str();
+ }
+};
+
+class UDS : public FullstackFixture {
+ public:
+ UDS(Service* service) : FullstackFixture(service, MakeAddress()) {}
+
+ private:
+ static grpc::string MakeAddress() {
+ int port = grpc_pick_unused_port_or_die(); // just for a unique id - not a
+ // real port
+ std::stringstream addr;
+ addr << "unix:/tmp/bm_fullstack." << port;
+ return addr.str();
+ }
+};
+
+class EndpointPairFixture : public BaseFixture {
+ public:
+ EndpointPairFixture(Service* service, grpc_endpoint_pair endpoints)
+ : endpoint_pair_(endpoints) {
+ ServerBuilder b;
+ cq_ = b.AddCompletionQueue(true);
+ b.RegisterService(service);
+ ApplyCommonServerBuilderConfig(&b);
+ server_ = b.BuildAndStart();
+
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+
+ /* add server endpoint to server_
+ * */
+ {
+ const grpc_channel_args* server_args =
+ grpc_server_get_channel_args(server_->c_server());
+ server_transport_ = grpc_create_chttp2_transport(
+ &exec_ctx, server_args, endpoints.server, 0 /* is_client */);
+
+ grpc_pollset** pollsets;
+ size_t num_pollsets = 0;
+ grpc_server_get_pollsets(server_->c_server(), &pollsets, &num_pollsets);
+
+ for (size_t i = 0; i < num_pollsets; i++) {
+ grpc_endpoint_add_to_pollset(&exec_ctx, endpoints.server, pollsets[i]);
+ }
+
+ grpc_server_setup_transport(&exec_ctx, server_->c_server(),
+ server_transport_, NULL, server_args);
+ grpc_chttp2_transport_start_reading(&exec_ctx, server_transport_, NULL);
+ }
+
+ /* create channel */
+ {
+ ChannelArguments args;
+ args.SetString(GRPC_ARG_DEFAULT_AUTHORITY, "test.authority");
+ ApplyCommonChannelArguments(&args);
+
+ grpc_channel_args c_args = args.c_channel_args();
+ client_transport_ =
+ grpc_create_chttp2_transport(&exec_ctx, &c_args, endpoints.client, 1);
+ GPR_ASSERT(client_transport_);
+ grpc_channel* channel =
+ grpc_channel_create(&exec_ctx, "target", &c_args,
+ GRPC_CLIENT_DIRECT_CHANNEL, client_transport_);
+ grpc_chttp2_transport_start_reading(&exec_ctx, client_transport_, NULL);
+
+ channel_ = CreateChannelInternal("", channel);
+ }
+
+ grpc_exec_ctx_finish(&exec_ctx);
+ }
+
+ virtual ~EndpointPairFixture() {
+ server_->Shutdown();
+ cq_->Shutdown();
+ void* tag;
+ bool ok;
+ while (cq_->Next(&tag, &ok)) {
+ }
+ }
+
+ ServerCompletionQueue* cq() { return cq_.get(); }
+ std::shared_ptr<Channel> channel() { return channel_; }
+
+ protected:
+ grpc_endpoint_pair endpoint_pair_;
+ grpc_transport* client_transport_;
+ grpc_transport* server_transport_;
+
+ private:
+ std::unique_ptr<Server> server_;
+ std::unique_ptr<ServerCompletionQueue> cq_;
+ std::shared_ptr<Channel> channel_;
+};
+
+class SockPair : public EndpointPairFixture {
+ public:
+ SockPair(Service* service)
+ : EndpointPairFixture(service, grpc_iomgr_create_endpoint_pair(
+ "test", Library::get().rq(), 8192)) {}
+};
+
+class InProcessCHTTP2 : public EndpointPairFixture {
+ public:
+ InProcessCHTTP2(Service* service)
+ : EndpointPairFixture(service, MakeEndpoints()) {}
+
+ void AddToLabel(std::ostream& out, benchmark::State& state) {
+ EndpointPairFixture::AddToLabel(out, state);
+ out << " writes/iter:"
+ << ((double)stats_.num_writes / (double)state.iterations());
+ }
+
+ private:
+ grpc_passthru_endpoint_stats stats_;
+
+ grpc_endpoint_pair MakeEndpoints() {
+ grpc_endpoint_pair p;
+ grpc_passthru_endpoint_create(&p.client, &p.server, Library::get().rq(),
+ &stats_);
+ return p;
+ }
+};
+
+} // namespace testing
+} // namespace grpc
+
+#endif
diff --git a/test/cpp/microbenchmarks/helpers.cc b/test/cpp/microbenchmarks/helpers.cc
new file mode 100644
index 0000000000..d277c5984c
--- /dev/null
+++ b/test/cpp/microbenchmarks/helpers.cc
@@ -0,0 +1,65 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "test/cpp/microbenchmarks/helpers.h"
+
+void TrackCounters::Finish(benchmark::State &state) {
+ std::ostringstream out;
+ AddToLabel(out, state);
+ auto label = out.str();
+ if (label.length() && label[0] == ' ') {
+ label = label.substr(1);
+ }
+ state.SetLabel(label);
+}
+
+void TrackCounters::AddToLabel(std::ostream &out, benchmark::State &state) {
+#ifdef GPR_LOW_LEVEL_COUNTERS
+ grpc_memory_counters counters_at_end = grpc_memory_counters_snapshot();
+ out << " locks/iter:" << ((double)(gpr_atm_no_barrier_load(&gpr_mu_locks) -
+ mu_locks_at_start_) /
+ (double)state.iterations())
+ << " atm_cas/iter:"
+ << ((double)(gpr_atm_no_barrier_load(&gpr_counter_atm_cas) -
+ atm_cas_at_start_) /
+ (double)state.iterations())
+ << " atm_add/iter:"
+ << ((double)(gpr_atm_no_barrier_load(&gpr_counter_atm_add) -
+ atm_add_at_start_) /
+ (double)state.iterations())
+ << " allocs/iter:"
+ << ((double)(counters_at_end.total_allocs_absolute -
+ counters_at_start_.total_allocs_absolute) /
+ (double)state.iterations());
+#endif
+}
diff --git a/test/cpp/microbenchmarks/helpers.h b/test/cpp/microbenchmarks/helpers.h
new file mode 100644
index 0000000000..f44b7cf83a
--- /dev/null
+++ b/test/cpp/microbenchmarks/helpers.h
@@ -0,0 +1,93 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#ifndef TEST_CPP_MICROBENCHMARKS_COUNTERS_H
+#define TEST_CPP_MICROBENCHMARKS_COUNTERS_H
+
+#include <sstream>
+
+extern "C" {
+#include <grpc/support/port_platform.h>
+#include "test/core/util/memory_counters.h"
+}
+
+#include <grpc++/impl/grpc_library.h>
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+class Library {
+ public:
+ static Library& get() {
+ static Library lib;
+ return lib;
+ }
+
+ grpc_resource_quota* rq() { return rq_; }
+
+ private:
+ Library() {
+#ifdef GPR_LOW_LEVEL_COUNTERS
+ grpc_memory_counters_init();
+#endif
+ init_lib_.init();
+ rq_ = grpc_resource_quota_create("bm");
+ }
+
+ ~Library() { init_lib_.shutdown(); }
+
+ grpc::internal::GrpcLibrary init_lib_;
+ grpc_resource_quota* rq_;
+};
+
+#ifdef GPR_LOW_LEVEL_COUNTERS
+extern "C" gpr_atm gpr_mu_locks;
+extern "C" gpr_atm gpr_counter_atm_cas;
+extern "C" gpr_atm gpr_counter_atm_add;
+#endif
+
+class TrackCounters {
+ public:
+ virtual void Finish(benchmark::State& state);
+ virtual void AddToLabel(std::ostream& out, benchmark::State& state);
+
+ private:
+#ifdef GPR_LOW_LEVEL_COUNTERS
+ const size_t mu_locks_at_start_ = gpr_atm_no_barrier_load(&gpr_mu_locks);
+ const size_t atm_cas_at_start_ =
+ gpr_atm_no_barrier_load(&gpr_counter_atm_cas);
+ const size_t atm_add_at_start_ =
+ gpr_atm_no_barrier_load(&gpr_counter_atm_add);
+ grpc_memory_counters counters_at_start_ = grpc_memory_counters_snapshot();
+#endif
+};
+
+#endif
diff --git a/test/cpp/qps/client.h b/test/cpp/qps/client.h
index baa9304cc2..25a19a5a74 100644
--- a/test/cpp/qps/client.h
+++ b/test/cpp/qps/client.h
@@ -46,7 +46,7 @@
#include <grpc/support/log.h>
#include <grpc/support/time.h>
-#include "src/proto/grpc/testing/payloads.grpc.pb.h"
+#include "src/proto/grpc/testing/payloads.pb.h"
#include "src/proto/grpc/testing/services.grpc.pb.h"
#include "test/cpp/qps/histogram.h"
diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc
index 4032039ea1..396d308e2a 100644
--- a/test/cpp/qps/client_async.cc
+++ b/test/cpp/qps/client_async.cc
@@ -112,7 +112,9 @@ class ClientRpcContextUnaryImpl : public ClientRpcContext {
next_state_ = State::RESP_DONE;
return true;
case State::RESP_DONE:
- entry->set_value((UsageTimer::Now() - start_) * 1e9);
+ if (status_.ok()) {
+ entry->set_value((UsageTimer::Now() - start_) * 1e9);
+ }
callback_(status_, &response_, entry);
next_state_ = State::INVALID;
return false;
diff --git a/test/cpp/qps/client_sync.cc b/test/cpp/qps/client_sync.cc
index 498416c64a..a944c45496 100644
--- a/test/cpp/qps/client_sync.cc
+++ b/test/cpp/qps/client_sync.cc
@@ -129,7 +129,9 @@ class SynchronousUnaryClient final : public SynchronousClient {
grpc::ClientContext context;
grpc::Status s =
stub->UnaryCall(&context, request_, &responses_[thread_idx]);
- entry->set_value((UsageTimer::Now() - start) * 1e9);
+ if (s.ok()) {
+ entry->set_value((UsageTimer::Now() - start) * 1e9);
+ }
entry->set_status(s.error_code());
return true;
}
@@ -154,7 +156,7 @@ class SynchronousStreamingClient final : public SynchronousClient {
(*stream)->WritesDone();
Status s = (*stream)->Finish();
if (!s.ok()) {
- gpr_log(GPR_ERROR, "Stream %zu received an error %s", i,
+ gpr_log(GPR_ERROR, "Stream %" PRIuPTR " received an error %s", i,
s.error_message().c_str());
}
}
@@ -170,8 +172,17 @@ class SynchronousStreamingClient final : public SynchronousClient {
if (stream_[thread_idx]->Write(request_) &&
stream_[thread_idx]->Read(&responses_[thread_idx])) {
entry->set_value((UsageTimer::Now() - start) * 1e9);
+ // don't set the status since there isn't one yet
return true;
}
+ stream_[thread_idx]->WritesDone();
+ Status s = stream_[thread_idx]->Finish();
+ // don't set the value since the stream is failed and shouldn't be timed
+ entry->set_status(s.error_code());
+ if (!s.ok()) {
+ gpr_log(GPR_ERROR, "Stream %" PRIuPTR " received an error %s", thread_idx,
+ s.error_message().c_str());
+ }
auto* stub = channels_[thread_idx % channels_.size()].get_stub();
context_[thread_idx].~ClientContext();
new (&context_[thread_idx]) ClientContext();
diff --git a/test/cpp/qps/driver.h b/test/cpp/qps/driver.h
index e72d30a4ef..dd32a16c87 100644
--- a/test/cpp/qps/driver.h
+++ b/test/cpp/qps/driver.h
@@ -36,7 +36,7 @@
#include <memory>
-#include "src/proto/grpc/testing/control.grpc.pb.h"
+#include "src/proto/grpc/testing/control.pb.h"
#include "test/cpp/qps/histogram.h"
namespace grpc {
diff --git a/test/cpp/qps/histogram.h b/test/cpp/qps/histogram.h
index acb415f0a1..470a394301 100644
--- a/test/cpp/qps/histogram.h
+++ b/test/cpp/qps/histogram.h
@@ -35,7 +35,7 @@
#define TEST_QPS_HISTOGRAM_H
#include <grpc/support/histogram.h>
-#include "src/proto/grpc/testing/stats.grpc.pb.h"
+#include "src/proto/grpc/testing/stats.pb.h"
namespace grpc {
namespace testing {
diff --git a/test/cpp/qps/qps_json_driver.cc b/test/cpp/qps/qps_json_driver.cc
index ddaaa7ca75..bd2c1f0ec6 100644
--- a/test/cpp/qps/qps_json_driver.cc
+++ b/test/cpp/qps/qps_json_driver.cc
@@ -31,6 +31,7 @@
*
*/
+#include <iostream>
#include <memory>
#include <set>
diff --git a/test/cpp/qps/server.h b/test/cpp/qps/server.h
index 821d5935be..8fbf37a095 100644
--- a/test/cpp/qps/server.h
+++ b/test/cpp/qps/server.h
@@ -38,8 +38,8 @@
#include <grpc/support/cpu.h>
#include <vector>
-#include "src/proto/grpc/testing/control.grpc.pb.h"
-#include "src/proto/grpc/testing/messages.grpc.pb.h"
+#include "src/proto/grpc/testing/control.pb.h"
+#include "src/proto/grpc/testing/messages.pb.h"
#include "test/core/end2end/data/ssl_test_data.h"
#include "test/core/util/port.h"
#include "test/cpp/qps/usage_timer.h"
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index b3a06aeaf5..b58d91eea6 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -103,24 +103,25 @@ class AsyncQpsServerTest final : public grpc::testing::Server {
server_ = builder.BuildAndStart();
- using namespace std::placeholders;
-
auto process_rpc_bound =
- std::bind(process_rpc, config.payload_config(), _1, _2);
+ std::bind(process_rpc, config.payload_config(), std::placeholders::_1,
+ std::placeholders::_2);
for (int i = 0; i < 15000; i++) {
for (int j = 0; j < num_threads; j++) {
if (request_unary_function) {
- auto request_unary =
- std::bind(request_unary_function, &async_service_, _1, _2, _3,
- srv_cqs_[j].get(), srv_cqs_[j].get(), _4);
+ auto request_unary = std::bind(
+ request_unary_function, &async_service_, std::placeholders::_1,
+ std::placeholders::_2, std::placeholders::_3, srv_cqs_[j].get(),
+ srv_cqs_[j].get(), std::placeholders::_4);
contexts_.emplace_back(
new ServerRpcContextUnaryImpl(request_unary, process_rpc_bound));
}
if (request_streaming_function) {
- auto request_streaming =
- std::bind(request_streaming_function, &async_service_, _1, _2,
- srv_cqs_[j].get(), srv_cqs_[j].get(), _3);
+ auto request_streaming = std::bind(
+ request_streaming_function, &async_service_,
+ std::placeholders::_1, std::placeholders::_2, srv_cqs_[j].get(),
+ srv_cqs_[j].get(), std::placeholders::_3);
contexts_.emplace_back(new ServerRpcContextStreamingImpl(
request_streaming, process_rpc_bound));
}
diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc
index 8076a4a6b9..f79284d225 100644
--- a/test/cpp/qps/server_sync.cc
+++ b/test/cpp/qps/server_sync.cc
@@ -74,7 +74,9 @@ class BenchmarkServiceImpl final : public BenchmarkService::Service {
return Status(grpc::StatusCode::INTERNAL, "Error creating payload.");
}
}
- stream->Write(response);
+ if (!stream->Write(response)) {
+ return Status(StatusCode::INTERNAL, "Server couldn't respond");
+ }
}
return Status::OK;
}
diff --git a/test/cpp/server/server_builder_test.cc b/test/cpp/server/server_builder_test.cc
new file mode 100644
index 0000000000..1d9eda17b4
--- /dev/null
+++ b/test/cpp/server/server_builder_test.cc
@@ -0,0 +1,96 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc++/impl/codegen/config.h>
+#include <gtest/gtest.h>
+
+#include <grpc++/server.h>
+#include <grpc++/server_builder.h>
+
+#include "src/proto/grpc/testing/echo.grpc.pb.h"
+#include "test/core/util/port.h"
+
+namespace grpc {
+namespace {
+
+testing::EchoTestService::Service g_service;
+
+grpc::string MakePort() {
+ std::ostringstream s;
+ int p = grpc_pick_unused_port_or_die();
+ s << "localhost:" << p;
+ return s.str();
+}
+
+grpc::string g_port = MakePort();
+
+TEST(ServerBuilderTest, NoOp) { ServerBuilder b; }
+
+TEST(ServerBuilderTest, CreateServerNoPorts) {
+ ServerBuilder().RegisterService(&g_service).BuildAndStart()->Shutdown();
+}
+
+TEST(ServerBuilderTest, CreateServerOnePort) {
+ ServerBuilder()
+ .RegisterService(&g_service)
+ .AddListeningPort(g_port, InsecureServerCredentials())
+ .BuildAndStart()
+ ->Shutdown();
+}
+
+TEST(ServerBuilderTest, CreateServerRepeatedPort) {
+ ServerBuilder()
+ .RegisterService(&g_service)
+ .AddListeningPort(g_port, InsecureServerCredentials())
+ .AddListeningPort(g_port, InsecureServerCredentials())
+ .BuildAndStart()
+ ->Shutdown();
+}
+
+TEST(ServerBuilderTest, CreateServerRepeatedPortWithDisallowedReusePort) {
+ EXPECT_EQ(ServerBuilder()
+ .RegisterService(&g_service)
+ .AddListeningPort(g_port, InsecureServerCredentials())
+ .AddListeningPort(g_port, InsecureServerCredentials())
+ .AddChannelArgument(GRPC_ARG_ALLOW_REUSEPORT, 0)
+ .BuildAndStart(),
+ nullptr);
+}
+
+} // namespace
+} // namespace grpc
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/test/http2_test/http2_server_health_check.py b/test/http2_test/http2_server_health_check.py
new file mode 100644
index 0000000000..dd9402b855
--- /dev/null
+++ b/test/http2_test/http2_server_health_check.py
@@ -0,0 +1,49 @@
+# 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.
+
+import argparse
+import hyper
+import sys
+
+# Utility to healthcheck the http2 server. Used when starting the server to
+# verify that the server is live before tests begin.
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser()
+ parser.add_argument('--server_host', type=str, default='localhost')
+ parser.add_argument('--server_port', type=int, default=8080)
+ args = parser.parse_args()
+ server_host = args.server_host
+ server_port = args.server_port
+ conn = hyper.HTTP20Connection('%s:%d' % (server_host, server_port))
+ conn.request('POST', '/grpc.testing.TestService/UnaryCall')
+ resp = conn.get_response()
+ if resp.headers.get('grpc-encoding') is None:
+ sys.exit(1)
+ else:
+ sys.exit(0)
diff --git a/test/http2_test/http2_test_server.py b/test/http2_test/http2_test_server.py
index abde3433ad..46c3e00d18 100644
--- a/test/http2_test/http2_test_server.py
+++ b/test/http2_test/http2_test_server.py
@@ -31,6 +31,7 @@
import argparse
import logging
+import sys
import twisted
import twisted.internet
import twisted.internet.endpoints
@@ -53,9 +54,11 @@ _TEST_CASE_MAPPING = {
'max_streams': test_max_streams.TestcaseSettingsMaxStreams,
}
+_exit_code = 0
+
class H2Factory(twisted.internet.protocol.Factory):
def __init__(self, testcase):
- logging.info('Creating H2Factory for new connection.')
+ logging.info('Creating H2Factory for new connection (%s)', testcase)
self._num_streams = 0
self._testcase = testcase
@@ -83,6 +86,17 @@ def parse_arguments():
)
return parser.parse_args()
+def listen(endpoint, test_case):
+ deferred = endpoint.listen(H2Factory(test_case))
+ def listen_error(reason):
+ # If listening fails, we stop the reactor and exit the program
+ # with exit code 1.
+ global _exit_code
+ _exit_code = 1
+ logging.error('Listening failed: %s' % reason.value)
+ twisted.internet.reactor.stop()
+ deferred.addErrback(listen_error)
+
def start_test_servers(base_port):
""" Start one server per test case on incrementing port numbers
beginning with base_port """
@@ -92,7 +106,9 @@ def start_test_servers(base_port):
logging.warning('serving on port %d : %s'%(portnum, test_case))
endpoint = twisted.internet.endpoints.TCP4ServerEndpoint(
twisted.internet.reactor, portnum, backlog=128)
- endpoint.listen(H2Factory(test_case))
+ # Wait until the reactor is running before calling endpoint.listen().
+ twisted.internet.reactor.callWhenRunning(listen, endpoint, test_case)
+
index += 1
if __name__ == '__main__':
@@ -102,3 +118,4 @@ if __name__ == '__main__':
args = parse_arguments()
start_test_servers(args.base_port)
twisted.internet.reactor.run()
+ sys.exit(_exit_code)