diff --git a/test/cpp/microbenchmarks/bm_pollset.cc b/test/cpp/microbenchmarks/bm_pollset.cc index 9d7fac39c77..da06eae5078 100644 --- a/test/cpp/microbenchmarks/bm_pollset.cc +++ b/test/cpp/microbenchmarks/bm_pollset.cc @@ -35,10 +35,13 @@ #include #include +#include +#include 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" } @@ -47,6 +50,12 @@ extern "C" { #include +#ifdef GRPC_LINUX_MULTIPOLL_WITH_EPOLL +#include +#include +#include +#endif + auto& force_library_initialization = Library::get(); static void shutdown_ps(grpc_exec_ctx* exec_ctx, void* ps, grpc_error* error) { @@ -76,6 +85,46 @@ static void BM_CreateDestroyPollset(benchmark::State& 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 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(); @@ -115,7 +164,41 @@ grpc_closure* MakeClosure(F f, grpc_closure_scheduler* scheduler) { return new C(f, scheduler); } -static void BM_PollAfterWakeup(benchmark::State& state) { +#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(gpr_zalloc(ps_sz)); @@ -159,6 +242,6 @@ static void BM_PollAfterWakeup(benchmark::State& state) { gpr_free(ps); track_counters.Finish(state); } -BENCHMARK(BM_PollAfterWakeup); +BENCHMARK(BM_SingleThreadPollOneFd); BENCHMARK_MAIN();