Skip to content

Commit

Permalink
Merge pull request grpc#10531 from sreecha/bm_cq_asan
Browse files Browse the repository at this point in the history
Fix asan bug in bm_cq_multiple_threads
  • Loading branch information
sreecha committed Apr 10, 2017
2 parents 47b49ce + 1f0c827 commit 921b896
Showing 1 changed file with 32 additions and 14 deletions.
46 changes: 32 additions & 14 deletions test/cpp/microbenchmarks/bm_cq_multiple_threads.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
#include <atomic>

#include <grpc/grpc.h>
#include <grpc/support/alloc.h>
#include <grpc/support/log.h>
#include "test/cpp/microbenchmarks/helpers.h"

extern "C" {
Expand All @@ -51,13 +53,10 @@ struct grpc_pollset {
namespace grpc {
namespace testing {

static void* make_tag(int i) { return (void*)(intptr_t)i; }
static void* g_tag = (void*)(intptr_t)10; // Some random number
static grpc_completion_queue* g_cq;
static grpc_event_engine_vtable g_vtable;

static __thread int g_thread_idx;
static __thread grpc_cq_completion g_cq_completion;

static void pollset_shutdown(grpc_exec_ctx* exec_ctx, grpc_pollset* ps,
grpc_closure* closure) {
grpc_closure_sched(exec_ctx, closure, GRPC_ERROR_NONE);
Expand All @@ -76,15 +75,18 @@ static grpc_error* pollset_kick(grpc_pollset* p, grpc_pollset_worker* worker) {

/* Callback when the tag is dequeued from the completion queue. Does nothing */
static void cq_done_cb(grpc_exec_ctx* exec_ctx, void* done_arg,
grpc_cq_completion* cq_completion) {}
grpc_cq_completion* cq_completion) {
gpr_free(cq_completion);
}

/* Queues a completion tag. ZERO polling overhead */
static grpc_error* pollset_work(grpc_exec_ctx* exec_ctx, grpc_pollset* ps,
grpc_pollset_worker** worker, gpr_timespec now,
gpr_timespec deadline) {
gpr_mu_unlock(&ps->mu);
grpc_cq_end_op(exec_ctx, g_cq, make_tag(g_thread_idx), GRPC_ERROR_NONE,
cq_done_cb, NULL, &g_cq_completion);
grpc_cq_begin_op(g_cq, g_tag);
grpc_cq_end_op(exec_ctx, g_cq, g_tag, GRPC_ERROR_NONE, cq_done_cb, NULL,
(grpc_cq_completion*)gpr_malloc(sizeof(grpc_cq_completion)));
grpc_exec_ctx_flush(exec_ctx);
gpr_mu_lock(&ps->mu);
return GRPC_ERROR_NONE;
Expand All @@ -109,26 +111,42 @@ static void setup() {
g_cq = grpc_completion_queue_create(NULL);
}

static void teardown() {
grpc_completion_queue_shutdown(g_cq);
grpc_completion_queue_destroy(g_cq);
}

/* A few notes about Multi-threaded benchmarks:
Setup:
The benchmark framework ensures that none of the threads proceed beyond the
state.KeepRunning() call unless all the threads have called state.keepRunning
atleast once. So it is safe to do the initialization in one of the threads
before state.KeepRunning() is called.
Teardown:
The benchmark framework also ensures that no thread is running the benchmark
code (i.e the code between two successive calls of state.KeepRunning()) if
state.KeepRunning() returns false. So it is safe to do the teardown in one
of the threads after state.keepRunning() returns false.
*/
static void BM_Cq_Throughput(benchmark::State& state) {
TrackCounters track_counters;
gpr_timespec deadline = gpr_inf_past(GPR_CLOCK_MONOTONIC);
gpr_timespec deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);

if (state.thread_index == 0) {
setup();
}

while (state.KeepRunning()) {
g_thread_idx = state.thread_index;
void* dummy_tag = make_tag(g_thread_idx);
grpc_cq_begin_op(g_cq, dummy_tag);
grpc_completion_queue_next(g_cq, deadline, NULL);
GPR_ASSERT(grpc_completion_queue_next(g_cq, deadline, NULL).type ==
GRPC_OP_COMPLETE);
}

state.SetItemsProcessed(state.iterations());

if (state.thread_index == 0) {
grpc_completion_queue_shutdown(g_cq);
grpc_completion_queue_destroy(g_cq);
teardown();
}

track_counters.Finish(state);
Expand Down

0 comments on commit 921b896

Please sign in to comment.