blob: 76d5030276934d1a3aaffb1b204f3d2f366d829b [file] [log] [blame]
Craig Tillerfd044b82017-02-15 16:15:48 -08001/*
2 *
Craig Tiller1d773992017-02-21 16:36:51 -08003 * Copyright 2017, Google Inc.
Craig Tillerfd044b82017-02-15 16:15:48 -08004 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following disclaimer
14 * in the documentation and/or other materials provided with the
15 * distribution.
16 * * Neither the name of Google Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 *
32 */
33
34/* This benchmark exists to ensure that the benchmark integration is
35 * working */
36
Craig Tillerbe42e1c2017-02-16 09:25:23 -080037#include <string.h>
Craig Tillera25c9b42017-02-15 17:19:22 -080038#include <sstream>
39
Craig Tillerfd044b82017-02-15 16:15:48 -080040#include <grpc++/support/channel_arguments.h>
41#include <grpc/grpc.h>
42#include <grpc/support/alloc.h>
Craig Tiller571b7ff2017-02-15 17:10:53 -080043#include <grpc/support/string_util.h>
Craig Tillerfd044b82017-02-15 16:15:48 -080044
45extern "C" {
46#include "src/core/ext/client_channel/client_channel.h"
Craig Tiller3a04deb2017-02-15 23:01:47 -080047#include "src/core/ext/load_reporting/load_reporting_filter.h"
Craig Tillerfd044b82017-02-15 16:15:48 -080048#include "src/core/lib/channel/channel_stack.h"
Craig Tiller571b7ff2017-02-15 17:10:53 -080049#include "src/core/lib/channel/compress_filter.h"
50#include "src/core/lib/channel/connected_channel.h"
51#include "src/core/lib/channel/deadline_filter.h"
52#include "src/core/lib/channel/http_client_filter.h"
53#include "src/core/lib/channel/http_server_filter.h"
54#include "src/core/lib/channel/message_size_filter.h"
55#include "src/core/lib/transport/transport_impl.h"
Craig Tillerfd044b82017-02-15 16:15:48 -080056}
57
58#include "third_party/benchmark/include/benchmark/benchmark.h"
59
60static struct Init {
61 Init() { grpc_init(); }
62 ~Init() { grpc_shutdown(); }
63} g_init;
64
Craig Tiller571b7ff2017-02-15 17:10:53 -080065static void BM_InsecureChannelWithDefaults(benchmark::State &state) {
66 grpc_channel *channel =
Craig Tillerfd044b82017-02-15 16:15:48 -080067 grpc_insecure_channel_create("localhost:12345", NULL, NULL);
Craig Tiller571b7ff2017-02-15 17:10:53 -080068 grpc_completion_queue *cq = grpc_completion_queue_create(NULL);
Craig Tillerfd044b82017-02-15 16:15:48 -080069 grpc_slice method = grpc_slice_from_static_string("/foo/bar");
70 gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
71 while (state.KeepRunning()) {
72 grpc_call_destroy(grpc_channel_create_call(channel, NULL,
73 GRPC_PROPAGATE_DEFAULTS, cq,
74 method, NULL, deadline, NULL));
75 }
76 grpc_channel_destroy(channel);
Craig Tiller385b0092017-02-22 13:45:01 -080077 grpc_completion_queue_destroy(cq);
Craig Tillerfd044b82017-02-15 16:15:48 -080078}
79BENCHMARK(BM_InsecureChannelWithDefaults);
80
Craig Tiller571b7ff2017-02-15 17:10:53 -080081static void FilterDestroy(grpc_exec_ctx *exec_ctx, void *arg,
82 grpc_error *error) {
Craig Tillerfd044b82017-02-15 16:15:48 -080083 gpr_free(arg);
84}
85
Craig Tiller571b7ff2017-02-15 17:10:53 -080086static void DoNothing(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {}
Craig Tillerfd044b82017-02-15 16:15:48 -080087
88class FakeClientChannelFactory : public grpc_client_channel_factory {
89 public:
90 FakeClientChannelFactory() { vtable = &vtable_; }
91
92 private:
Craig Tiller571b7ff2017-02-15 17:10:53 -080093 static void NoRef(grpc_client_channel_factory *factory) {}
94 static void NoUnref(grpc_exec_ctx *exec_ctx,
95 grpc_client_channel_factory *factory) {}
96 static grpc_subchannel *CreateSubchannel(grpc_exec_ctx *exec_ctx,
97 grpc_client_channel_factory *factory,
98 const grpc_subchannel_args *args) {
Craig Tillerfd044b82017-02-15 16:15:48 -080099 return nullptr;
100 }
Craig Tiller571b7ff2017-02-15 17:10:53 -0800101 static grpc_channel *CreateClientChannel(grpc_exec_ctx *exec_ctx,
102 grpc_client_channel_factory *factory,
103 const char *target,
Craig Tillerfd044b82017-02-15 16:15:48 -0800104 grpc_client_channel_type type,
Craig Tiller571b7ff2017-02-15 17:10:53 -0800105 const grpc_channel_args *args) {
Craig Tillerfd044b82017-02-15 16:15:48 -0800106 return nullptr;
107 }
108
109 static const grpc_client_channel_factory_vtable vtable_;
110};
111
112const grpc_client_channel_factory_vtable FakeClientChannelFactory::vtable_ = {
113 NoRef, NoUnref, CreateSubchannel, CreateClientChannel};
114
Craig Tiller571b7ff2017-02-15 17:10:53 -0800115static grpc_arg StringArg(const char *key, const char *value) {
Craig Tillerfd044b82017-02-15 16:15:48 -0800116 grpc_arg a;
117 a.type = GRPC_ARG_STRING;
Craig Tiller571b7ff2017-02-15 17:10:53 -0800118 a.key = const_cast<char *>(key);
119 a.value.string = const_cast<char *>(value);
Craig Tillerfd044b82017-02-15 16:15:48 -0800120 return a;
121}
122
Craig Tiller571b7ff2017-02-15 17:10:53 -0800123enum FixtureFlags : uint32_t {
124 CHECKS_NOT_LAST = 1,
125 REQUIRES_TRANSPORT = 2,
126};
127
128template <const grpc_channel_filter *kFilter, uint32_t kFlags>
129struct Fixture {
130 const grpc_channel_filter *filter = kFilter;
131 const uint32_t flags = kFlags;
132};
133
134namespace dummy_filter {
135
136static void StartTransportStreamOp(grpc_exec_ctx *exec_ctx,
137 grpc_call_element *elem,
138 grpc_transport_stream_op *op) {}
139
140static void StartTransportOp(grpc_exec_ctx *exec_ctx,
141 grpc_channel_element *elem,
142 grpc_transport_op *op) {}
143
144static grpc_error *InitCallElem(grpc_exec_ctx *exec_ctx,
145 grpc_call_element *elem,
Craig Tillerc52ba3a2017-02-15 22:57:43 -0800146 const grpc_call_element_args *args) {
Craig Tiller571b7ff2017-02-15 17:10:53 -0800147 return GRPC_ERROR_NONE;
148}
149
150static void SetPollsetOrPollsetSet(grpc_exec_ctx *exec_ctx,
151 grpc_call_element *elem,
152 grpc_polling_entity *pollent) {}
153
154static void DestroyCallElem(grpc_exec_ctx *exec_ctx, grpc_call_element *elem,
155 const grpc_call_final_info *final_info,
156 void *and_free_memory) {}
157
158grpc_error *InitChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
159 grpc_channel_element_args *args) {
160 return GRPC_ERROR_NONE;
161}
162
163void DestroyChannelElem(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem) {}
164
165char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_call_element *elem) {
166 return gpr_strdup("peer");
167}
168
169void GetChannelInfo(grpc_exec_ctx *exec_ctx, grpc_channel_element *elem,
170 const grpc_channel_info *channel_info) {}
171
172static const grpc_channel_filter dummy_filter = {StartTransportStreamOp,
173 StartTransportOp,
174 0,
175 InitCallElem,
176 SetPollsetOrPollsetSet,
177 DestroyCallElem,
178 0,
179 InitChannelElem,
180 DestroyChannelElem,
181 GetPeer,
182 GetChannelInfo,
183 "dummy_filter"};
184
185} // namespace dummy_filter
186
187namespace dummy_transport {
188
189/* Memory required for a single stream element - this is allocated by upper
190 layers and initialized by the transport */
191size_t sizeof_stream; /* = sizeof(transport stream) */
192
193/* name of this transport implementation */
194const char *name;
195
196/* implementation of grpc_transport_init_stream */
197int InitStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
198 grpc_stream *stream, grpc_stream_refcount *refcount,
199 const void *server_data) {
200 return 0;
201}
202
203/* implementation of grpc_transport_set_pollset */
204void SetPollset(grpc_exec_ctx *exec_ctx, grpc_transport *self,
205 grpc_stream *stream, grpc_pollset *pollset) {}
206
207/* implementation of grpc_transport_set_pollset */
208void SetPollsetSet(grpc_exec_ctx *exec_ctx, grpc_transport *self,
209 grpc_stream *stream, grpc_pollset_set *pollset_set) {}
210
211/* implementation of grpc_transport_perform_stream_op */
212void PerformStreamOp(grpc_exec_ctx *exec_ctx, grpc_transport *self,
Craig Tiller4f60fbf2017-02-15 23:50:36 -0800213 grpc_stream *stream, grpc_transport_stream_op *op) {
214 grpc_closure_sched(exec_ctx, op->on_complete, GRPC_ERROR_NONE);
215}
Craig Tiller571b7ff2017-02-15 17:10:53 -0800216
217/* implementation of grpc_transport_perform_op */
218void PerformOp(grpc_exec_ctx *exec_ctx, grpc_transport *self,
219 grpc_transport_op *op) {}
220
221/* implementation of grpc_transport_destroy_stream */
222void DestroyStream(grpc_exec_ctx *exec_ctx, grpc_transport *self,
223 grpc_stream *stream, void *and_free_memory) {}
224
225/* implementation of grpc_transport_destroy */
226void Destroy(grpc_exec_ctx *exec_ctx, grpc_transport *self) {}
227
228/* implementation of grpc_transport_get_peer */
229char *GetPeer(grpc_exec_ctx *exec_ctx, grpc_transport *self) {
230 return gpr_strdup("transport_peer");
231}
232
233/* implementation of grpc_transport_get_endpoint */
234grpc_endpoint *GetEndpoint(grpc_exec_ctx *exec_ctx, grpc_transport *self) {
235 return nullptr;
236}
237
238static const grpc_transport_vtable dummy_transport_vtable = {
239 0, "dummy_http2", InitStream,
240 SetPollset, SetPollsetSet, PerformStreamOp,
241 PerformOp, DestroyStream, Destroy,
242 GetPeer, GetEndpoint};
243
244static grpc_transport dummy_transport = {&dummy_transport_vtable};
245
246} // namespace dummy_transport
247
Craig Tiller385b0092017-02-22 13:45:01 -0800248class NoOp {
249 public:
250 class Op {
251 public:
252 Op(grpc_exec_ctx *exec_ctx, NoOp *p, grpc_call_stack *s) {}
253 void Finish(grpc_exec_ctx *exec_ctx) {}
254 };
255};
256
257class SendEmptyMetadata {
258 public:
259 SendEmptyMetadata() {
260 memset(&op_, 0, sizeof(op_));
261 op_.on_complete = grpc_closure_init(&closure_, DoNothing, nullptr,
262 grpc_schedule_on_exec_ctx);
263 }
264
265 class Op {
266 public:
267 Op(grpc_exec_ctx *exec_ctx, SendEmptyMetadata *p, grpc_call_stack *s) {
268 grpc_metadata_batch_init(&batch_);
269 p->op_.send_initial_metadata = &batch_;
270 }
271 void Finish(grpc_exec_ctx *exec_ctx) {
272 grpc_metadata_batch_destroy(exec_ctx, &batch_);
273 }
274
275 private:
276 grpc_metadata_batch batch_;
277 };
278
279 private:
280 const gpr_timespec deadline_ = gpr_inf_future(GPR_CLOCK_MONOTONIC);
281 const gpr_timespec start_time_ = gpr_now(GPR_CLOCK_MONOTONIC);
282 const grpc_slice method_ = grpc_slice_from_static_string("/foo/bar");
283 grpc_transport_stream_op op_;
284 grpc_closure closure_;
285};
286
287// Test a filter in isolation. Fixture specifies the filter under test (use the
288// Fixture<> template to specify this), and TestOp defines some unit of work to
289// perform on said filter.
290template <class Fixture, class TestOp>
291static void BM_IsolatedFilter(benchmark::State &state) {
Craig Tiller571b7ff2017-02-15 17:10:53 -0800292 Fixture fixture;
Craig Tillera25c9b42017-02-15 17:19:22 -0800293 std::ostringstream label;
Craig Tiller571b7ff2017-02-15 17:10:53 -0800294
Craig Tillerfd044b82017-02-15 16:15:48 -0800295 std::vector<grpc_arg> args;
296 FakeClientChannelFactory fake_client_channel_factory;
297 args.push_back(grpc_client_channel_factory_create_channel_arg(
298 &fake_client_channel_factory));
299 args.push_back(StringArg(GRPC_ARG_SERVER_URI, "localhost"));
300
301 grpc_channel_args channel_args = {args.size(), &args[0]};
302
Craig Tiller571b7ff2017-02-15 17:10:53 -0800303 std::vector<const grpc_channel_filter *> filters;
Craig Tiller4bba37c2017-02-15 17:16:44 -0800304 if (fixture.filter != nullptr) {
305 filters.push_back(fixture.filter);
306 }
Craig Tiller571b7ff2017-02-15 17:10:53 -0800307 if (fixture.flags & CHECKS_NOT_LAST) {
308 filters.push_back(&dummy_filter::dummy_filter);
Craig Tiller385b0092017-02-22 13:45:01 -0800309 label << " #has_dummy_filter";
Craig Tiller571b7ff2017-02-15 17:10:53 -0800310 }
311
Craig Tillerfd044b82017-02-15 16:15:48 -0800312 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
Craig Tiller571b7ff2017-02-15 17:10:53 -0800313 size_t channel_size = grpc_channel_stack_size(&filters[0], filters.size());
314 grpc_channel_stack *channel_stack =
Craig Tillerb82b3d02017-02-23 12:50:05 -0800315 static_cast<grpc_channel_stack *>(gpr_zalloc(channel_size));
Craig Tillerfd044b82017-02-15 16:15:48 -0800316 GPR_ASSERT(GRPC_LOG_IF_ERROR(
317 "call_stack_init",
318 grpc_channel_stack_init(&exec_ctx, 1, FilterDestroy, channel_stack,
Craig Tiller571b7ff2017-02-15 17:10:53 -0800319 &filters[0], filters.size(), &channel_args,
320 fixture.flags & REQUIRES_TRANSPORT
321 ? &dummy_transport::dummy_transport
322 : nullptr,
323 "CHANNEL", channel_stack)));
Craig Tillerfd044b82017-02-15 16:15:48 -0800324 grpc_exec_ctx_flush(&exec_ctx);
Craig Tiller571b7ff2017-02-15 17:10:53 -0800325 grpc_call_stack *call_stack = static_cast<grpc_call_stack *>(
Craig Tillerb82b3d02017-02-23 12:50:05 -0800326 gpr_zalloc(channel_stack->call_stack_size));
Craig Tillerfd044b82017-02-15 16:15:48 -0800327 gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
328 gpr_timespec start_time = gpr_now(GPR_CLOCK_MONOTONIC);
329 grpc_slice method = grpc_slice_from_static_string("/foo/bar");
330 grpc_call_final_info final_info;
Craig Tiller385b0092017-02-22 13:45:01 -0800331 TestOp test_op_data;
Craig Tillerfd044b82017-02-15 16:15:48 -0800332 while (state.KeepRunning()) {
333 GRPC_ERROR_UNREF(grpc_call_stack_init(&exec_ctx, channel_stack, 1,
334 DoNothing, NULL, NULL, NULL, method,
335 start_time, deadline, call_stack));
Craig Tiller385b0092017-02-22 13:45:01 -0800336 typename TestOp::Op op(&exec_ctx, &test_op_data, call_stack);
Craig Tillerfd044b82017-02-15 16:15:48 -0800337 grpc_call_stack_destroy(&exec_ctx, call_stack, &final_info, NULL);
Craig Tiller385b0092017-02-22 13:45:01 -0800338 op.Finish(&exec_ctx);
Craig Tillerfd044b82017-02-15 16:15:48 -0800339 grpc_exec_ctx_flush(&exec_ctx);
340 }
Craig Tiller571b7ff2017-02-15 17:10:53 -0800341 grpc_channel_stack_destroy(&exec_ctx, channel_stack);
Craig Tillerfd044b82017-02-15 16:15:48 -0800342 grpc_exec_ctx_finish(&exec_ctx);
Craig Tiller2ec37e12017-02-22 10:26:52 -0800343 gpr_free(channel_stack);
Craig Tiller385b0092017-02-22 13:45:01 -0800344 gpr_free(call_stack);
Craig Tiller4f60fbf2017-02-15 23:50:36 -0800345
346 state.SetLabel(label.str());
347}
348
Craig Tiller4bba37c2017-02-15 17:16:44 -0800349typedef Fixture<nullptr, 0> NoFilter;
Craig Tiller385b0092017-02-22 13:45:01 -0800350BENCHMARK_TEMPLATE(BM_IsolatedFilter, NoFilter, NoOp);
Craig Tiller571b7ff2017-02-15 17:10:53 -0800351typedef Fixture<&dummy_filter::dummy_filter, 0> DummyFilter;
Craig Tiller385b0092017-02-22 13:45:01 -0800352BENCHMARK_TEMPLATE(BM_IsolatedFilter, DummyFilter, NoOp);
353BENCHMARK_TEMPLATE(BM_IsolatedFilter, DummyFilter, SendEmptyMetadata);
Craig Tiller571b7ff2017-02-15 17:10:53 -0800354typedef Fixture<&grpc_client_channel_filter, 0> ClientChannelFilter;
Craig Tiller385b0092017-02-22 13:45:01 -0800355BENCHMARK_TEMPLATE(BM_IsolatedFilter, ClientChannelFilter, NoOp);
Craig Tiller571b7ff2017-02-15 17:10:53 -0800356typedef Fixture<&grpc_compress_filter, CHECKS_NOT_LAST> CompressFilter;
Craig Tiller385b0092017-02-22 13:45:01 -0800357BENCHMARK_TEMPLATE(BM_IsolatedFilter, CompressFilter, NoOp);
358BENCHMARK_TEMPLATE(BM_IsolatedFilter, CompressFilter, SendEmptyMetadata);
Craig Tiller571b7ff2017-02-15 17:10:53 -0800359typedef Fixture<&grpc_client_deadline_filter, CHECKS_NOT_LAST>
360 ClientDeadlineFilter;
Craig Tiller385b0092017-02-22 13:45:01 -0800361BENCHMARK_TEMPLATE(BM_IsolatedFilter, ClientDeadlineFilter, NoOp);
362BENCHMARK_TEMPLATE(BM_IsolatedFilter, ClientDeadlineFilter, SendEmptyMetadata);
Craig Tiller571b7ff2017-02-15 17:10:53 -0800363typedef Fixture<&grpc_server_deadline_filter, CHECKS_NOT_LAST>
364 ServerDeadlineFilter;
Craig Tiller385b0092017-02-22 13:45:01 -0800365BENCHMARK_TEMPLATE(BM_IsolatedFilter, ServerDeadlineFilter, NoOp);
366BENCHMARK_TEMPLATE(BM_IsolatedFilter, ServerDeadlineFilter, SendEmptyMetadata);
Craig Tiller571b7ff2017-02-15 17:10:53 -0800367typedef Fixture<&grpc_http_client_filter, CHECKS_NOT_LAST | REQUIRES_TRANSPORT>
368 HttpClientFilter;
Craig Tiller385b0092017-02-22 13:45:01 -0800369BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpClientFilter, NoOp);
370BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpClientFilter, SendEmptyMetadata);
Craig Tiller571b7ff2017-02-15 17:10:53 -0800371typedef Fixture<&grpc_http_server_filter, CHECKS_NOT_LAST> HttpServerFilter;
Craig Tiller385b0092017-02-22 13:45:01 -0800372BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpServerFilter, NoOp);
373BENCHMARK_TEMPLATE(BM_IsolatedFilter, HttpServerFilter, SendEmptyMetadata);
Craig Tiller571b7ff2017-02-15 17:10:53 -0800374typedef Fixture<&grpc_message_size_filter, CHECKS_NOT_LAST> MessageSizeFilter;
Craig Tiller385b0092017-02-22 13:45:01 -0800375BENCHMARK_TEMPLATE(BM_IsolatedFilter, MessageSizeFilter, NoOp);
376BENCHMARK_TEMPLATE(BM_IsolatedFilter, MessageSizeFilter, SendEmptyMetadata);
Craig Tiller3a04deb2017-02-15 23:01:47 -0800377typedef Fixture<&grpc_load_reporting_filter, CHECKS_NOT_LAST>
378 LoadReportingFilter;
Craig Tiller385b0092017-02-22 13:45:01 -0800379BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, NoOp);
380BENCHMARK_TEMPLATE(BM_IsolatedFilter, LoadReportingFilter, SendEmptyMetadata);
Craig Tillerfd044b82017-02-15 16:15:48 -0800381
382BENCHMARK_MAIN();