Use base64 encoded length for decoder table size
diff --git a/src/core/ext/transport/chttp2/transport/hpack_encoder.c b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
index 819addd..ef89f1c 100644
--- a/src/core/ext/transport/chttp2/transport/hpack_encoder.c
+++ b/src/core/ext/transport/chttp2/transport/hpack_encoder.c
@@ -49,6 +49,7 @@
 #include "src/core/ext/transport/chttp2/transport/hpack_table.h"
 #include "src/core/ext/transport/chttp2/transport/timeout_encoding.h"
 #include "src/core/ext/transport/chttp2/transport/varint.h"
+#include "src/core/lib/transport/metadata.h"
 #include "src/core/lib/transport/static_metadata.h"
 
 #define HASH_FRAGMENT_1(x) ((x)&255)
@@ -178,8 +179,7 @@
   uint32_t key_hash = elem->key->hash;
   uint32_t elem_hash = GRPC_MDSTR_KV_HASH(key_hash, elem->value->hash);
   uint32_t new_index = c->tail_remote_index + c->table_elems + 1;
-  size_t elem_size = 32 + GPR_SLICE_LENGTH(elem->key->slice) +
-                     GPR_SLICE_LENGTH(elem->value->slice);
+  size_t elem_size = grpc_mdelem_get_size_in_hpack_table(elem);
 
   GPR_ASSERT(elem_size < 65536);
 
@@ -395,8 +395,7 @@
   }
 
   /* should this elem be in the table? */
-  decoder_space_usage = 32 + GPR_SLICE_LENGTH(elem->key->slice) +
-                        GPR_SLICE_LENGTH(elem->value->slice);
+  decoder_space_usage = grpc_mdelem_get_size_in_hpack_table(elem);
   should_add_elem = decoder_space_usage < MAX_DECODER_SPACE_USAGE &&
                     c->filter_elems[HASH_FRAGMENT_1(elem_hash)] >=
                         c->filter_elems_sum / ONE_ON_ADD_PROBABILITY;
diff --git a/src/core/lib/transport/metadata.c b/src/core/lib/transport/metadata.c
index 451c8d1..b1005f3 100644
--- a/src/core/lib/transport/metadata.c
+++ b/src/core/lib/transport/metadata.c
@@ -38,6 +38,7 @@
 #include <string.h>
 
 #include <grpc/compression.h>
+#include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/atm.h>
 #include <grpc/support/log.h>
@@ -93,6 +94,9 @@
 
   gpr_slice base64_and_huffman;
 
+  uint8_t has_size_in_decoder_table;
+  size_t size_in_decoder_table;
+
   struct internal_string *bucket_next;
 } internal_string;
 
@@ -407,6 +411,8 @@
   }
   s->has_base64_and_huffman_encoded = 0;
   s->hash = hash;
+  s->has_size_in_decoder_table = 0;
+  s->size_in_decoder_table = 0;
   s->bucket_next = shard->strs[idx];
   shard->strs[idx] = s;
 
@@ -576,6 +582,29 @@
       grpc_mdstr_from_string(key), grpc_mdstr_from_buffer(value, value_length));
 }
 
+size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem) {
+  size_t overhead_and_key = 32 + GPR_SLICE_LENGTH(elem->key->slice);
+  if (is_mdstr_static(elem->value)) {
+    return overhead_and_key + GPR_SLICE_LENGTH(elem->value->slice);
+  } else {
+    internal_string *is = (internal_string *)elem->value;
+    size_t value_len = GPR_SLICE_LENGTH(is->slice);
+    static const uint8_t tail_xtra[3] = {0, 2, 3};
+    if (is->has_size_in_decoder_table == 0) {
+      is->has_size_in_decoder_table = 1;
+      if (grpc_is_binary_header(
+              (const char *)GPR_SLICE_START_PTR(elem->key->slice),
+              GPR_SLICE_LENGTH(elem->key->slice))) {
+        is->size_in_decoder_table =
+            value_len / 3 * 4 + tail_xtra[value_len % 3];
+      } else {
+        is->size_in_decoder_table = value_len;
+      }
+    }
+    return overhead_and_key + is->size_in_decoder_table;
+  }
+}
+
 grpc_mdelem *grpc_mdelem_ref(grpc_mdelem *gmd DEBUG_ARGS) {
   internal_metadata *md = (internal_metadata *)gmd;
   if (is_mdelem_static(gmd)) return gmd;
diff --git a/src/core/lib/transport/metadata.h b/src/core/lib/transport/metadata.h
index d72ec9a..9705a7f 100644
--- a/src/core/lib/transport/metadata.h
+++ b/src/core/lib/transport/metadata.h
@@ -110,6 +110,8 @@
                                                 const uint8_t *value,
                                                 size_t value_length);
 
+size_t grpc_mdelem_get_size_in_hpack_table(grpc_mdelem *elem);
+
 /* Mutator and accessor for grpc_mdelem user data. The destructor function
    is used as a type tag and is checked during user_data fetch. */
 void *grpc_mdelem_get_user_data(grpc_mdelem *md,