diff --git a/CMakeLists.txt b/CMakeLists.txt
index b628843e245781eea67b263a828153d59be3dc9a..65df5d7f7c12773ba717dc66c9a93b16a0587e3c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -8044,7 +8044,9 @@ target_link_libraries(bm_pollset
   ${_gRPC_ALLTARGETS_LIBRARIES}
   grpc_benchmark
   benchmark
+  grpc++_test_util
   grpc_test_util
+  grpc++
   grpc
   gpr_test_util
   gpr
diff --git a/Makefile b/Makefile
index bdc3bc72d5f032b9f29d9dbb7fbd8061f20afbe3..9e74ffb94ffc87aa11117860e06d799c51957b27 100644
--- a/Makefile
+++ b/Makefile
@@ -13097,16 +13097,16 @@ $(BINDIR)/$(CONFIG)/bm_pollset: protobuf_dep_error
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_pollset: $(PROTOBUF_DEP) $(BM_POLLSET_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(BINDIR)/$(CONFIG)/bm_pollset: $(PROTOBUF_DEP) $(BM_POLLSET_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 	$(E) "[LD]      Linking $@"
 	$(Q) mkdir -p `dirname $@`
-	$(Q) $(LDXX) $(LDFLAGS) $(BM_POLLSET_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_pollset
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_POLLSET_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBSXX) $(LDLIBS_PROTOBUF) $(LDLIBS) $(LDLIBS_SECURE) $(GTEST_LIB) -o $(BINDIR)/$(CONFIG)/bm_pollset
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_pollset.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_pollset.o:  $(LIBDIR)/$(CONFIG)/libgrpc_benchmark.a $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc++_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc++.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
 
 deps_bm_pollset: $(BM_POLLSET_OBJS:.o=.dep)
 
diff --git a/build.yaml b/build.yaml
index c7e99cb214e4149904790f50812101c0499cd6fe..1534cf9a1254d2240bbe5570b59f79dca704e3cd 100644
--- a/build.yaml
+++ b/build.yaml
@@ -3276,7 +3276,9 @@ targets:
   deps:
   - grpc_benchmark
   - benchmark
+  - grpc++_test_util
   - grpc_test_util
+  - grpc++
   - grpc
   - gpr_test_util
   - gpr
diff --git a/test/cpp/microbenchmarks/bm_pollset.cc b/test/cpp/microbenchmarks/bm_pollset.cc
index f7c3b7951d27d1a2e960545aece297be72bdd857..0f3d3cef66a9e9c4fae30305e078d6a4dfe9b373 100644
--- a/test/cpp/microbenchmarks/bm_pollset.cc
+++ b/test/cpp/microbenchmarks/bm_pollset.cc
@@ -35,16 +35,27 @@
 
 #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) {
@@ -74,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<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();
@@ -99,21 +150,61 @@ static void BM_PollEmptyPollset(benchmark::State& state) {
 }
 BENCHMARK(BM_PollEmptyPollset);
 
+class Closure : public grpc_closure {
+ public:
+  virtual ~Closure() {}
+};
+
 template <class F>
-grpc_closure* MakeClosure(F f, grpc_closure_scheduler* scheduler) {
-  struct C : public grpc_closure {
+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) {
-      static_cast<C*>(arg)->f_();
+      C* p = static_cast<C*>(arg);
+      p->f_();
     }
     F f_;
   };
   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<grpc_pollset*>(gpr_zalloc(ps_sz));
@@ -127,7 +218,7 @@ static void BM_PollAfterWakeup(benchmark::State& state) {
   grpc_fd* wakeup = grpc_fd_create(wakeup_fd.read_fd, "wakeup_read");
   grpc_pollset_add_fd(&exec_ctx, ps, wakeup);
   bool done = false;
-  grpc_closure* continue_closure = MakeClosure(
+  Closure* continue_closure = MakeClosure(
       [&]() {
         GRPC_ERROR_UNREF(grpc_wakeup_fd_consume_wakeup(&wakeup_fd));
         if (!state.KeepRunning()) {
@@ -156,7 +247,8 @@ static void BM_PollAfterWakeup(benchmark::State& state) {
   grpc_wakeup_fd_destroy(&wakeup_fd);
   gpr_free(ps);
   track_counters.Finish(state);
+  delete continue_closure;
 }
-BENCHMARK(BM_PollAfterWakeup);
+BENCHMARK(BM_SingleThreadPollOneFd);
 
 BENCHMARK_MAIN();
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 58d929806fd246cc87f45f8fc7a7571ede106f91..c0cd6c0496451957ecc1e2827c735d7b469718b0 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -2645,6 +2645,8 @@
       "gpr", 
       "gpr_test_util", 
       "grpc", 
+      "grpc++", 
+      "grpc++_test_util", 
       "grpc_benchmark", 
       "grpc_test_util"
     ],