diff --git a/Makefile b/Makefile
index e738c11b1df640f2c07ad8b043179e258f753028..76bdd001d180aa3cd8a37007350911834e03135a 100644
--- a/Makefile
+++ b/Makefile
@@ -212,6 +212,14 @@ CPPFLAGS_mutrace = -O3 -fno-omit-frame-pointer
 LDFLAGS_mutrace = -rdynamic
 DEFINES_mutrace = NDEBUG
 
+VALID_CONFIG_counters = 1
+CC_counters = $(DEFAULT_CC)
+CXX_counters = $(DEFAULT_CXX)
+LD_counters = $(DEFAULT_CC)
+LDXX_counters = $(DEFAULT_CXX)
+CPPFLAGS_counters = -O2 -DGPR_MU_COUNTERS
+DEFINES_counters = NDEBUG
+
 
 
 # General settings.
diff --git a/build.yaml b/build.yaml
index da55eb198977c380ffe00f8c5a7b94c0110e15dd..0b4c08578471c4f391cc778158342b2b2a27611d 100644
--- a/build.yaml
+++ b/build.yaml
@@ -3851,6 +3851,9 @@ configs:
   basicprof:
     CPPFLAGS: -O2 -DGRPC_BASIC_PROFILER -DGRPC_TIMERS_RDTSC
     DEFINES: NDEBUG
+  counters:
+    CPPFLAGS: -O2 -DGPR_MU_COUNTERS
+    DEFINES: NDEBUG
   dbg:
     CPPFLAGS: -O0
     DEFINES: _DEBUG DEBUG
diff --git a/src/core/lib/support/sync_posix.c b/src/core/lib/support/sync_posix.c
index dcb0969a4ea1df63934840e9f0944225a4858e04..de0f0484b57f0f1cf091590b03cfc4bd9abf8de0 100644
--- a/src/core/lib/support/sync_posix.c
+++ b/src/core/lib/support/sync_posix.c
@@ -42,11 +42,18 @@
 #include <time.h>
 #include "src/core/lib/profiling/timers.h"
 
+#ifdef GPR_MU_COUNTERS
+gpr_atm grpc_mu_locks = 0;
+#endif
+
 void gpr_mu_init(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_init(mu, NULL) == 0); }
 
 void gpr_mu_destroy(gpr_mu* mu) { GPR_ASSERT(pthread_mutex_destroy(mu) == 0); }
 
 void gpr_mu_lock(gpr_mu* mu) {
+#ifdef GPR_MU_COUNTERS
+  gpr_atm_no_barrier_fetch_add(&grpc_mu_locks, 1);
+#endif
   GPR_TIMER_BEGIN("gpr_mu_lock", 0);
   GPR_ASSERT(pthread_mutex_lock(mu) == 0);
   GPR_TIMER_END("gpr_mu_lock", 0);
diff --git a/test/cpp/microbenchmarks/bm_fullstack.cc b/test/cpp/microbenchmarks/bm_fullstack.cc
index dd180de48a5c01dc2bd93ba64502ca854aef12be..a870ff74555e0690b9c9c7170a369a9ba355865a 100644
--- a/test/cpp/microbenchmarks/bm_fullstack.cc
+++ b/test/cpp/microbenchmarks/bm_fullstack.cc
@@ -54,6 +54,7 @@ extern "C" {
 #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"
 }
@@ -67,6 +68,7 @@ namespace testing {
 static class InitializeStuff {
  public:
   InitializeStuff() {
+    grpc_memory_counters_init();
     init_lib_.init();
     rq_ = grpc_resource_quota_create("bm");
   }
@@ -94,7 +96,42 @@ static void ApplyCommonChannelArguments(ChannelArguments* c) {
   c->SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, INT_MAX);
 }
 
-class FullstackFixture {
+#ifdef GPR_MU_COUNTERS
+extern "C" gpr_atm grpc_mu_locks;
+#endif
+
+class BaseFixture {
+ public:
+  void Finish(benchmark::State& s) {
+    std::ostringstream out;
+    this->AddToLabel(out, s);
+#ifdef GPR_MU_COUNTERS
+    out << " locks/iter:" << ((double)(gpr_atm_no_barrier_load(&grpc_mu_locks) -
+                                       mu_locks_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_MU_COUNTERS
+  const size_t mu_locks_at_start_ = gpr_atm_no_barrier_load(&grpc_mu_locks);
+#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;
@@ -130,7 +167,7 @@ class TCP : public FullstackFixture {
  public:
   TCP(Service* service) : FullstackFixture(service, MakeAddress()) {}
 
-  void Finish(benchmark::State& state) {}
+  void AddToLabel(std::ostream& out, benchmark::State& state) {}
 
  private:
   static grpc::string MakeAddress() {
@@ -145,7 +182,7 @@ class UDS : public FullstackFixture {
  public:
   UDS(Service* service) : FullstackFixture(service, MakeAddress()) {}
 
-  void Finish(benchmark::State& state) {}
+  void AddToLabel(std::ostream& out, benchmark::State& state) override {}
 
  private:
   static grpc::string MakeAddress() {
@@ -157,7 +194,7 @@ class UDS : public FullstackFixture {
   }
 };
 
-class EndpointPairFixture {
+class EndpointPairFixture : public BaseFixture {
  public:
   EndpointPairFixture(Service* service, grpc_endpoint_pair endpoints) {
     ServerBuilder b;
@@ -233,7 +270,7 @@ class SockPair : public EndpointPairFixture {
                                          "test", initialize_stuff.rq(), 8192)) {
   }
 
-  void Finish(benchmark::State& state) {}
+  void AddToLabel(std::ostream& out, benchmark::State& state) {}
 };
 
 class InProcessCHTTP2 : public EndpointPairFixture {
@@ -241,11 +278,9 @@ class InProcessCHTTP2 : public EndpointPairFixture {
   InProcessCHTTP2(Service* service)
       : EndpointPairFixture(service, MakeEndpoints()) {}
 
-  void Finish(benchmark::State& state) {
-    std::ostringstream out;
-    out << "writes/iteration:"
+  void AddToLabel(std::ostream& out, benchmark::State& state) {
+    out << " writes/iter:"
         << ((double)stats_.num_writes / (double)state.iterations());
-    state.SetLabel(out.str());
   }
 
  private:
diff --git a/tools/run_tests/generated/configs.json b/tools/run_tests/generated/configs.json
index 091f5d9823989462ded238622940906e10f94520..9173bd7c19c8e25348e7bbab911b89a909c2e465 100644
--- a/tools/run_tests/generated/configs.json
+++ b/tools/run_tests/generated/configs.json
@@ -66,5 +66,8 @@
   }, 
   {
     "config": "mutrace"
+  }, 
+  {
+    "config": "counters"
   }
 ]
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index 75efd4db071c0b89b5c628d0c140f259ef821450..1c8b57e431c5dad5092666b52420109e31d74913 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -39282,6 +39282,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39317,6 +39318,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39352,6 +39354,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39387,6 +39390,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39424,6 +39428,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39461,6 +39466,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39496,6 +39502,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39531,6 +39538,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39566,6 +39574,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39601,6 +39610,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39636,6 +39646,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39671,6 +39682,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39706,6 +39718,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39741,6 +39754,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39776,6 +39790,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39811,6 +39826,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39846,6 +39862,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39881,6 +39898,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39916,6 +39934,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39951,6 +39970,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -39986,6 +40006,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40023,6 +40044,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40060,6 +40082,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40095,6 +40118,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40130,6 +40154,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40165,6 +40190,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40200,6 +40226,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40235,6 +40262,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40270,6 +40298,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40305,6 +40334,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40340,6 +40370,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40375,6 +40406,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40410,6 +40442,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind", 
@@ -40445,6 +40478,7 @@
       "asan-noleaks", 
       "asan-trace-cmp", 
       "basicprof", 
+      "counters", 
       "dbg", 
       "gcov", 
       "helgrind",