Merge branch 'bm_chttp2' into bm_meta
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b72b8e7..d1bc3bf 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -584,6 +584,9 @@
 if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
 add_dependencies(buildtests_cxx bm_fullstack)
 endif()
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+add_dependencies(buildtests_cxx bm_metadata)
+endif()
 add_dependencies(buildtests_cxx channel_arguments_test)
 add_dependencies(buildtests_cxx channel_filter_test)
 add_dependencies(buildtests_cxx cli_call_test)
@@ -7469,7 +7472,9 @@
   ${_gRPC_PROTOBUF_LIBRARIES}
   ${_gRPC_ALLTARGETS_LIBRARIES}
   benchmark
+  grpc++_test_util
   grpc_test_util
+  grpc++
   grpc
   gpr_test_util
   gpr
@@ -7593,6 +7598,42 @@
 endif()
 endif (gRPC_BUILD_TESTS)
 if (gRPC_BUILD_TESTS)
+if(_gRPC_PLATFORM_LINUX OR _gRPC_PLATFORM_MAC OR _gRPC_PLATFORM_POSIX)
+
+add_executable(bm_metadata
+  test/cpp/microbenchmarks/bm_metadata.cc
+  third_party/googletest/src/gtest-all.cc
+)
+
+
+target_include_directories(bm_metadata
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
+  PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include
+  PRIVATE ${BORINGSSL_ROOT_DIR}/include
+  PRIVATE ${PROTOBUF_ROOT_DIR}/src
+  PRIVATE ${BENCHMARK_ROOT_DIR}/include
+  PRIVATE ${ZLIB_ROOT_DIR}
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib
+  PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include
+  PRIVATE third_party/googletest/include
+  PRIVATE third_party/googletest
+  PRIVATE ${_gRPC_PROTO_GENS_DIR}
+)
+
+target_link_libraries(bm_metadata
+  ${_gRPC_PROTOBUF_LIBRARIES}
+  ${_gRPC_ALLTARGETS_LIBRARIES}
+  benchmark
+  grpc_test_util
+  grpc
+  gpr_test_util
+  gpr
+  ${_gRPC_GFLAGS_LIBRARIES}
+)
+
+endif()
+endif (gRPC_BUILD_TESTS)
+if (gRPC_BUILD_TESTS)
 
 add_executable(channel_arguments_test
   test/cpp/common/channel_arguments_test.cc
diff --git a/Makefile b/Makefile
index 1fff137..c8e1b10 100644
--- a/Makefile
+++ b/Makefile
@@ -1046,6 +1046,7 @@
 bm_cq: $(BINDIR)/$(CONFIG)/bm_cq
 bm_error: $(BINDIR)/$(CONFIG)/bm_error
 bm_fullstack: $(BINDIR)/$(CONFIG)/bm_fullstack
+bm_metadata: $(BINDIR)/$(CONFIG)/bm_metadata
 channel_arguments_test: $(BINDIR)/$(CONFIG)/channel_arguments_test
 channel_filter_test: $(BINDIR)/$(CONFIG)/channel_filter_test
 cli_call_test: $(BINDIR)/$(CONFIG)/cli_call_test
@@ -1455,6 +1456,7 @@
   $(BINDIR)/$(CONFIG)/bm_cq \
   $(BINDIR)/$(CONFIG)/bm_error \
   $(BINDIR)/$(CONFIG)/bm_fullstack \
+  $(BINDIR)/$(CONFIG)/bm_metadata \
   $(BINDIR)/$(CONFIG)/channel_arguments_test \
   $(BINDIR)/$(CONFIG)/channel_filter_test \
   $(BINDIR)/$(CONFIG)/cli_call_test \
@@ -1565,6 +1567,7 @@
   $(BINDIR)/$(CONFIG)/bm_cq \
   $(BINDIR)/$(CONFIG)/bm_error \
   $(BINDIR)/$(CONFIG)/bm_fullstack \
+  $(BINDIR)/$(CONFIG)/bm_metadata \
   $(BINDIR)/$(CONFIG)/channel_arguments_test \
   $(BINDIR)/$(CONFIG)/channel_filter_test \
   $(BINDIR)/$(CONFIG)/cli_call_test \
@@ -1892,6 +1895,8 @@
 	$(Q) $(BINDIR)/$(CONFIG)/bm_error || ( echo test bm_error failed ; exit 1 )
 	$(E) "[RUN]     Testing bm_fullstack"
 	$(Q) $(BINDIR)/$(CONFIG)/bm_fullstack || ( echo test bm_fullstack failed ; exit 1 )
+	$(E) "[RUN]     Testing bm_metadata"
+	$(Q) $(BINDIR)/$(CONFIG)/bm_metadata || ( echo test bm_metadata failed ; exit 1 )
 	$(E) "[RUN]     Testing channel_arguments_test"
 	$(Q) $(BINDIR)/$(CONFIG)/channel_arguments_test || ( echo test channel_arguments_test failed ; exit 1 )
 	$(E) "[RUN]     Testing channel_filter_test"
@@ -12416,16 +12421,16 @@
 
 else
 
-$(BINDIR)/$(CONFIG)/bm_closure: $(PROTOBUF_DEP) $(BM_CLOSURE_OBJS) $(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_closure: $(PROTOBUF_DEP) $(BM_CLOSURE_OBJS) $(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_CLOSURE_OBJS) $(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_closure
+	$(Q) $(LDXX) $(LDFLAGS) $(BM_CLOSURE_OBJS) $(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_closure
 
 endif
 
 endif
 
-$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_closure.o:  $(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_closure.o:  $(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_closure: $(BM_CLOSURE_OBJS:.o=.dep)
 
@@ -12565,6 +12570,49 @@
 endif
 
 
+BM_METADATA_SRC = \
+    test/cpp/microbenchmarks/bm_metadata.cc \
+
+BM_METADATA_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(BM_METADATA_SRC))))
+ifeq ($(NO_SECURE),true)
+
+# You can't build secure targets if you don't have OpenSSL.
+
+$(BINDIR)/$(CONFIG)/bm_metadata: openssl_dep_error
+
+else
+
+
+
+
+ifeq ($(NO_PROTOBUF),true)
+
+# You can't build the protoc plugins or protobuf-enabled targets if you don't have protobuf 3.0.0+.
+
+$(BINDIR)/$(CONFIG)/bm_metadata: protobuf_dep_error
+
+else
+
+$(BINDIR)/$(CONFIG)/bm_metadata: $(PROTOBUF_DEP) $(BM_METADATA_OBJS) $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.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_METADATA_OBJS) $(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_metadata
+
+endif
+
+endif
+
+$(OBJDIR)/$(CONFIG)/test/cpp/microbenchmarks/bm_metadata.o:  $(LIBDIR)/$(CONFIG)/libbenchmark.a $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a
+
+deps_bm_metadata: $(BM_METADATA_OBJS:.o=.dep)
+
+ifneq ($(NO_SECURE),true)
+ifneq ($(NO_DEPS),true)
+-include $(BM_METADATA_OBJS:.o=.dep)
+endif
+endif
+
+
 CHANNEL_ARGUMENTS_TEST_SRC = \
     test/cpp/common/channel_arguments_test.cc \
 
diff --git a/build.yaml b/build.yaml
index 4dca4d8..9c4da69 100644
--- a/build.yaml
+++ b/build.yaml
@@ -3006,7 +3006,9 @@
   - test/cpp/microbenchmarks/bm_closure.cc
   deps:
   - benchmark
+  - grpc++_test_util
   - grpc_test_util
+  - grpc++
   - grpc
   - gpr_test_util
   - gpr
@@ -3073,6 +3075,23 @@
   - mac
   - linux
   - posix
+- name: bm_metadata
+  build: test
+  language: c++
+  src:
+  - test/cpp/microbenchmarks/bm_metadata.cc
+  deps:
+  - benchmark
+  - grpc_test_util
+  - grpc
+  - gpr_test_util
+  - gpr
+  args:
+  - --benchmark_min_time=0
+  platforms:
+  - mac
+  - linux
+  - posix
 - name: channel_arguments_test
   gtest: true
   build: test
diff --git a/test/cpp/microbenchmarks/bm_metadata.cc b/test/cpp/microbenchmarks/bm_metadata.cc
new file mode 100644
index 0000000..7f81fba
--- /dev/null
+++ b/test/cpp/microbenchmarks/bm_metadata.cc
@@ -0,0 +1,282 @@
+/*
+ *
+ * Copyright 2015, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* Test out various metadata handling primitives */
+
+#include <grpc/grpc.h>
+
+extern "C" {
+#include "src/core/lib/transport/metadata.h"
+#include "src/core/lib/transport/static_metadata.h"
+}
+
+#include "third_party/benchmark/include/benchmark/benchmark.h"
+
+static class InitializeStuff {
+ public:
+  InitializeStuff() { grpc_init(); }
+  ~InitializeStuff() { grpc_shutdown(); }
+} initialize_stuff;
+
+static void BM_SliceFromStatic(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    benchmark::DoNotOptimize(grpc_slice_from_static_string("abc"));
+  }
+}
+BENCHMARK(BM_SliceFromStatic);
+
+static void BM_SliceFromCopied(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    grpc_slice_unref(grpc_slice_from_copied_string("abc"));
+  }
+}
+BENCHMARK(BM_SliceFromCopied);
+
+static void BM_SliceIntern(benchmark::State& state) {
+  gpr_slice slice = grpc_slice_from_static_string("abc");
+  while (state.KeepRunning()) {
+    grpc_slice_unref(grpc_slice_intern(slice));
+  }
+}
+BENCHMARK(BM_SliceIntern);
+
+static void BM_SliceReIntern(benchmark::State& state) {
+  gpr_slice slice = grpc_slice_intern(grpc_slice_from_static_string("abc"));
+  while (state.KeepRunning()) {
+    grpc_slice_unref(grpc_slice_intern(slice));
+  }
+  grpc_slice_unref(slice);
+}
+BENCHMARK(BM_SliceReIntern);
+
+static void BM_SliceInternStaticMetadata(benchmark::State& state) {
+  while (state.KeepRunning()) {
+    grpc_slice_intern(GRPC_MDSTR_GZIP);
+  }
+}
+BENCHMARK(BM_SliceInternStaticMetadata);
+
+static void BM_SliceInternEqualToStaticMetadata(benchmark::State& state) {
+  gpr_slice slice = grpc_slice_from_static_string("gzip");
+  while (state.KeepRunning()) {
+    grpc_slice_intern(slice);
+  }
+}
+BENCHMARK(BM_SliceInternEqualToStaticMetadata);
+
+static void BM_MetadataFromNonInternedSlices(benchmark::State& state) {
+  gpr_slice k = grpc_slice_from_static_string("key");
+  gpr_slice v = grpc_slice_from_static_string("value");
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataFromNonInternedSlices);
+
+static void BM_MetadataFromInternedSlices(benchmark::State& state) {
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value"));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+  grpc_slice_unref(v);
+}
+BENCHMARK(BM_MetadataFromInternedSlices);
+
+static void BM_MetadataFromInternedSlicesAlreadyInIndex(
+    benchmark::State& state) {
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value"));
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_mdelem seed = grpc_mdelem_create(&exec_ctx, k, v, NULL);
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, seed);
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+  grpc_slice_unref(v);
+}
+BENCHMARK(BM_MetadataFromInternedSlicesAlreadyInIndex);
+
+static void BM_MetadataFromInternedKey(benchmark::State& state) {
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_from_static_string("value");
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+}
+BENCHMARK(BM_MetadataFromInternedKey);
+
+static void BM_MetadataFromNonInternedSlicesWithBackingStore(
+    benchmark::State& state) {
+  gpr_slice k = grpc_slice_from_static_string("key");
+  gpr_slice v = grpc_slice_from_static_string("value");
+  char backing_store[sizeof(grpc_mdelem_data)];
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(
+        &exec_ctx,
+        grpc_mdelem_create(&exec_ctx, k, v,
+                           reinterpret_cast<grpc_mdelem_data*>(backing_store)));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataFromNonInternedSlicesWithBackingStore);
+
+static void BM_MetadataFromInternedSlicesWithBackingStore(
+    benchmark::State& state) {
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value"));
+  char backing_store[sizeof(grpc_mdelem_data)];
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(
+        &exec_ctx,
+        grpc_mdelem_create(&exec_ctx, k, v,
+                           reinterpret_cast<grpc_mdelem_data*>(backing_store)));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+  grpc_slice_unref(v);
+}
+BENCHMARK(BM_MetadataFromInternedSlicesWithBackingStore);
+
+static void BM_MetadataFromInternedKeyWithBackingStore(
+    benchmark::State& state) {
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_from_static_string("value");
+  char backing_store[sizeof(grpc_mdelem_data)];
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(
+        &exec_ctx,
+        grpc_mdelem_create(&exec_ctx, k, v,
+                           reinterpret_cast<grpc_mdelem_data*>(backing_store)));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+}
+BENCHMARK(BM_MetadataFromInternedKeyWithBackingStore);
+
+static void BM_MetadataFromStaticMetadataStrings(benchmark::State& state) {
+  gpr_slice k = GRPC_MDSTR_STATUS;
+  gpr_slice v = GRPC_MDSTR_200;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+}
+BENCHMARK(BM_MetadataFromStaticMetadataStrings);
+
+static void BM_MetadataFromStaticMetadataStringsNotIndexed(
+    benchmark::State& state) {
+  gpr_slice k = GRPC_MDSTR_STATUS;
+  gpr_slice v = GRPC_MDSTR_GZIP;
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, grpc_mdelem_create(&exec_ctx, k, v, NULL));
+  }
+  grpc_exec_ctx_finish(&exec_ctx);
+  grpc_slice_unref(k);
+}
+BENCHMARK(BM_MetadataFromStaticMetadataStringsNotIndexed);
+
+static void BM_MetadataRefUnrefExternal(benchmark::State& state) {
+  char backing_store[sizeof(grpc_mdelem_data)];
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_mdelem el =
+      grpc_mdelem_create(&exec_ctx, grpc_slice_from_static_string("a"),
+                         grpc_slice_from_static_string("b"),
+                         reinterpret_cast<grpc_mdelem_data*>(backing_store));
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el));
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, el);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataRefUnrefExternal);
+
+static void BM_MetadataRefUnrefInterned(benchmark::State& state) {
+  char backing_store[sizeof(grpc_mdelem_data)];
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  gpr_slice k = grpc_slice_intern(grpc_slice_from_static_string("key"));
+  gpr_slice v = grpc_slice_intern(grpc_slice_from_static_string("value"));
+  grpc_mdelem el = grpc_mdelem_create(
+      &exec_ctx, k, v, reinterpret_cast<grpc_mdelem_data*>(backing_store));
+  grpc_slice_unref(k);
+  grpc_slice_unref(v);
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el));
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, el);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataRefUnrefInterned);
+
+static void BM_MetadataRefUnrefAllocated(benchmark::State& state) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_mdelem el =
+      grpc_mdelem_create(&exec_ctx, grpc_slice_from_static_string("a"),
+                         grpc_slice_from_static_string("b"), NULL);
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el));
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, el);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataRefUnrefAllocated);
+
+static void BM_MetadataRefUnrefStatic(benchmark::State& state) {
+  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+  grpc_mdelem el =
+      grpc_mdelem_create(&exec_ctx, GRPC_MDSTR_STATUS, GRPC_MDSTR_200, NULL);
+  while (state.KeepRunning()) {
+    GRPC_MDELEM_UNREF(&exec_ctx, GRPC_MDELEM_REF(el));
+  }
+  GRPC_MDELEM_UNREF(&exec_ctx, el);
+  grpc_exec_ctx_finish(&exec_ctx);
+}
+BENCHMARK(BM_MetadataRefUnrefStatic);
+
+BENCHMARK_MAIN();
diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json
index 61c4f37..8403f06 100644
--- a/tools/run_tests/generated/sources_and_headers.json
+++ b/tools/run_tests/generated/sources_and_headers.json
@@ -2358,6 +2358,8 @@
       "gpr", 
       "gpr_test_util", 
       "grpc", 
+      "grpc++", 
+      "grpc++_test_util", 
       "grpc_test_util"
     ], 
     "headers": [], 
@@ -2432,6 +2434,24 @@
   }, 
   {
     "deps": [
+      "benchmark", 
+      "gpr", 
+      "gpr_test_util", 
+      "grpc", 
+      "grpc_test_util"
+    ], 
+    "headers": [], 
+    "is_filegroup": false, 
+    "language": "c++", 
+    "name": "bm_metadata", 
+    "src": [
+      "test/cpp/microbenchmarks/bm_metadata.cc"
+    ], 
+    "third_party": false, 
+    "type": "target"
+  }, 
+  {
+    "deps": [
       "gpr", 
       "grpc", 
       "grpc++"
diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json
index e112b93..8b18e2f 100644
--- a/tools/run_tests/generated/tests.json
+++ b/tools/run_tests/generated/tests.json
@@ -2580,6 +2580,28 @@
     ]
   }, 
   {
+    "args": [
+      "--benchmark_min_time=0"
+    ], 
+    "ci_platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ], 
+    "cpu_cost": 1.0, 
+    "exclude_configs": [], 
+    "exclude_iomgrs": [], 
+    "flaky": false, 
+    "gtest": false, 
+    "language": "c++", 
+    "name": "bm_metadata", 
+    "platforms": [
+      "linux", 
+      "mac", 
+      "posix"
+    ]
+  }, 
+  {
     "args": [], 
     "ci_platforms": [
       "linux", 
diff --git a/tools/run_tests/run_microbenchmark.py b/tools/run_tests/run_microbenchmark.py
index 8b74d31..7f871bf 100755
--- a/tools/run_tests/run_microbenchmark.py
+++ b/tools/run_tests/run_microbenchmark.py
@@ -204,7 +204,9 @@
                            'bm_cq',
                            'bm_call_create',
                            'bm_error',
-                           'bm_chttp2_hpack'],
+                           'bm_chttp2_hpack',
+                           'bm_metadata'],
+>>>>>>> b325a1dd4af3f3d3443da3e0ac0f007162c63772
                   nargs='+',
                   type=str,
                   help='Which microbenchmarks should be run')