Bug 1296280 (part 1) - Add telemetry for HPACK usage. r?mcmanus data-review=bsmedberg draft
authorNicholas Hurley <hurley@todesschaf.org>
Wed, 24 Aug 2016 06:38:52 -0700
changeset 416120 cecab777fb8f69e8f283576c045e2356117373c9
parent 414561 6a52d9c83f9755bac19c27d4afd227f4197b33a2
child 416121 238521d95e5fdbae495e1af5aa3bfa881e69b809
push id30030
push userbmo:hurley@todesschaf.org
push dateWed, 21 Sep 2016 13:34:37 +0000
reviewersmcmanus
bugs1296280
milestone51.0a1
Bug 1296280 (part 1) - Add telemetry for HPACK usage. r?mcmanus data-review=bsmedberg MozReview-Commit-ID: Hk5XNrj3Tbh
netwerk/protocol/http/Http2Compression.cpp
netwerk/protocol/http/Http2Compression.h
toolkit/components/telemetry/Histograms.json
--- a/netwerk/protocol/http/Http2Compression.cpp
+++ b/netwerk/protocol/http/Http2Compression.cpp
@@ -276,23 +276,31 @@ nvFIFO::operator[] (size_t index) const
   }
   return static_cast<nvPair *>(gStaticHeaders->ObjectAt(index));
 }
 
 Http2BaseCompressor::Http2BaseCompressor()
   : mOutput(nullptr)
   , mMaxBuffer(kDefaultMaxBuffer)
   , mMaxBufferSetting(kDefaultMaxBuffer)
+  , mPeakSize(0)
+  , mPeakCount(0)
 {
   mDynamicReporter = new HpackDynamicTableReporter(this);
   RegisterStrongMemoryReporter(mDynamicReporter);
 }
 
 Http2BaseCompressor::~Http2BaseCompressor()
 {
+  if (mPeakSize) {
+    Telemetry::Accumulate(mPeakSizeID, mPeakSize);
+  }
+  if (mPeakCount) {
+    Telemetry::Accumulate(mPeakCountID, mPeakCount);
+  }
   UnregisterStrongMemoryReporter(mDynamicReporter);
   mDynamicReporter->mCompressor = nullptr;
   mDynamicReporter = nullptr;
 }
 
 void
 Http2BaseCompressor::ClearHeaderTable()
 {
@@ -307,25 +315,40 @@ Http2BaseCompressor::SizeOfExcludingThis
     size += mHeaderTable[i]->SizeOfIncludingThis(aMallocSizeOf);
   }
   return size;
 }
 
 void
 Http2BaseCompressor::MakeRoom(uint32_t amount, const char *direction)
 {
+  uint32_t countEvicted = 0;
+  uint32_t bytesEvicted = 0;
+
   // make room in the header table
   while (mHeaderTable.VariableLength() && ((mHeaderTable.ByteCount() + amount) > mMaxBuffer)) {
     // NWGH - remove the "- 1" here
     uint32_t index = mHeaderTable.Length() - 1;
     LOG(("HTTP %s header table index %u %s %s removed for size.\n",
          direction, index, mHeaderTable[index]->mName.get(),
          mHeaderTable[index]->mValue.get()));
+    ++countEvicted;
+    bytesEvicted += mHeaderTable[index]->Size();
     mHeaderTable.RemoveElement();
   }
+
+  if (!strcmp(direction, "decompressor")) {
+    Telemetry::Accumulate(Telemetry::HPACK_ELEMENTS_EVICTED_DECOMPRESSOR, countEvicted);
+    Telemetry::Accumulate(Telemetry::HPACK_BYTES_EVICTED_DECOMPRESSOR, bytesEvicted);
+    Telemetry::Accumulate(Telemetry::HPACK_BYTES_EVICTED_RATIO_DECOMPRESSOR, (uint32_t)((100.0 * (double)bytesEvicted) / (double)amount));
+  } else {
+    Telemetry::Accumulate(Telemetry::HPACK_ELEMENTS_EVICTED_COMPRESSOR, countEvicted);
+    Telemetry::Accumulate(Telemetry::HPACK_BYTES_EVICTED_COMPRESSOR, bytesEvicted);
+    Telemetry::Accumulate(Telemetry::HPACK_BYTES_EVICTED_RATIO_COMPRESSOR, (uint32_t)((100.0 * (double)bytesEvicted) / (double)amount));
+  }
 }
 
 void
 Http2BaseCompressor::DumpState()
 {
   if (!LOG_ENABLED()) {
     return;
   }
@@ -547,17 +570,18 @@ Http2Decompressor::OutputHeader(const ns
     if (*cPtr == ':') {
       isColonHeader = true;
       break;
     } else if (*cPtr != ' ' && *cPtr != '\t') {
       isColonHeader = false;
       break;
     }
   }
-  if(isColonHeader) {
+
+  if (isColonHeader) {
     // :status is the only pseudo-header field allowed in received HEADERS frames, PUSH_PROMISE allows the other pseudo-header fields
     if (!name.EqualsLiteral(":status") && !mIsPush) {
       LOG(("HTTP Decompressor found illegal response pseudo-header %s", name.BeginReading()));
       return NS_ERROR_ILLEGAL_VALUE;
     }
     if (mSeenNonColonHeader) {
       LOG(("HTTP Decompressor found illegal : header %s", name.BeginReading()));
       return NS_ERROR_ILLEGAL_VALUE;
@@ -932,16 +956,26 @@ Http2Decompressor::DoLiteralWithIncremen
     return NS_OK;
   }
 
   MakeRoom(room, "decompressor");
 
   // Incremental Indexing implicitly adds a row to the header table.
   mHeaderTable.AddElement(name, value);
 
+  uint32_t currentSize = mHeaderTable.ByteCount();
+  if (currentSize > mPeakSize) {
+    mPeakSize = currentSize;
+  }
+
+  uint32_t currentCount = mHeaderTable.VariableLength();
+  if (currentCount > mPeakCount) {
+    mPeakCount = currentCount;
+  }
+
   LOG(("HTTP decompressor literal with index 0 %s %s\n",
        name.get(), value.get()));
 
   return NS_OK;
 }
 
 nsresult
 Http2Decompressor::DoLiteralNeverIndexed()
--- a/netwerk/protocol/http/Http2Compression.h
+++ b/netwerk/protocol/http/Http2Compression.h
@@ -8,16 +8,17 @@
 
 // HPACK - RFC 7541
 // https://www.rfc-editor.org/rfc/rfc7541.txt
 
 #include "mozilla/Attributes.h"
 #include "nsDeque.h"
 #include "nsString.h"
 #include "nsIMemoryReporter.h"
+#include "mozilla/Telemetry.h"
 
 namespace mozilla {
 namespace net {
 
 struct HuffmanIncomingTable;
 
 void Http2CompressionCleanup();
 
@@ -75,26 +76,35 @@ protected:
   virtual void SetMaxBufferSizeInternal(uint32_t maxBufferSize);
 
   nsACString *mOutput;
   nvFIFO mHeaderTable;
 
   uint32_t mMaxBuffer;
   uint32_t mMaxBufferSetting;
 
+  uint32_t mPeakSize;
+  uint32_t mPeakCount;
+  Telemetry::ID mPeakSizeID;
+  Telemetry::ID mPeakCountID;
+
 private:
   RefPtr<HpackDynamicTableReporter> mDynamicReporter;
 };
 
 class Http2Compressor;
 
 class Http2Decompressor final : public Http2BaseCompressor
 {
 public:
-  Http2Decompressor() { };
+  Http2Decompressor()
+  {
+    mPeakSizeID = Telemetry::HPACK_PEAK_SIZE_DECOMPRESSOR;
+    mPeakCountID = Telemetry::HPACK_PEAK_COUNT_DECOMPRESSOR;
+  };
   virtual ~Http2Decompressor() { } ;
 
   // NS_OK: Produces the working set of HTTP/1 formatted headers
   nsresult DecodeHeaderBlock(const uint8_t *data, uint32_t datalen,
                              nsACString &output, bool isPush);
 
   void GetStatus(nsACString &hdr) { hdr = mHeaderStatus; }
   void GetHost(nsACString &hdr) { hdr = mHeaderHost; }
@@ -139,17 +149,20 @@ private:
 
 
 class Http2Compressor final : public Http2BaseCompressor
 {
 public:
   Http2Compressor() : mParsedContentLength(-1),
                       mBufferSizeChangeWaiting(false),
                       mLowestBufferSizeWaiting(0)
-  { };
+  {
+    mPeakSizeID = Telemetry::HPACK_PEAK_SIZE_COMPRESSOR;
+    mPeakCountID = Telemetry::HPACK_PEAK_COUNT_COMPRESSOR;
+  };
   virtual ~Http2Compressor() { }
 
   // HTTP/1 formatted header block as input - HTTP/2 formatted
   // header block as output
   nsresult EncodeHeaderBlock(const nsCString &nvInput,
                              const nsACString &method, const nsACString &path,
                              const nsACString &host, const nsACString &scheme,
                              bool connectForm, nsACString &output);
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -1980,16 +1980,106 @@
     "description": "H2: goaway reason client sent from rfc 7540. 31 is none sent."
   },
   "SPDY_GOAWAY_PEER": {
     "expires_in_version": "never",
     "kind": "enumerated",
     "n_values": 32,
     "description": "H2: goaway reason from peer from rfc 7540. 31 is none received."
   },
+  "HPACK_ELEMENTS_EVICTED_DECOMPRESSOR": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 256,
+    "n_buckets": 50,
+    "description": "HPACK: Number of items removed from dynamic table to make room for 1 new item",
+    "alert_emails": ["necko@mozilla.com", "hurley@mozilla.com"],
+    "bug_numbers": [1296280]
+  },
+  "HPACK_BYTES_EVICTED_DECOMPRESSOR": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 8192,
+    "n_buckets": 50,
+    "description": "HPACK: Number of bytes removed from dynamic table to make room for 1 new item",
+    "alert_emails": ["necko@mozilla.com", "hurley@mozilla.com"],
+    "bug_numbers": [1296280]
+  },
+  "HPACK_BYTES_EVICTED_RATIO_DECOMPRESSOR": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 256,
+    "n_buckets": 50,
+    "description": "HPACK: Ratio of bytes evicted to bytes added (* 100)",
+    "alert_emails": ["necko@mozilla.com", "hurley@mozilla.com"],
+    "bug_numbers": [1296280]
+  },
+  "HPACK_PEAK_COUNT_DECOMPRESSOR": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 1024,
+    "n_buckets": 50,
+    "description": "HPACK: peak number of items in the dynamic table",
+    "alert_emails": ["necko@mozilla.com", "hurley@mozilla.com"],
+    "bug_numbers": [1296280]
+  },
+  "HPACK_PEAK_SIZE_DECOMPRESSOR": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 16384,
+    "n_buckets": 100,
+    "description": "HPACK: peak size in bytes of the table",
+    "alert_emails": ["necko@mozilla.com", "hurley@mozilla.com"],
+    "bug_numbers": [1296280]
+  },
+  "HPACK_ELEMENTS_EVICTED_COMPRESSOR": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 256,
+    "n_buckets": 50,
+    "description": "HPACK: Number of items removed from dynamic table to make room for 1 new item",
+    "alert_emails": ["necko@mozilla.com", "hurley@mozilla.com"],
+    "bug_numbers": [1296280]
+  },
+  "HPACK_BYTES_EVICTED_COMPRESSOR": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 8192,
+    "n_buckets": 50,
+    "description": "HPACK: Number of bytes removed from dynamic table to make room for 1 new item",
+    "alert_emails": ["necko@mozilla.com", "hurley@mozilla.com"],
+    "bug_numbers": [1296280]
+  },
+  "HPACK_BYTES_EVICTED_RATIO_COMPRESSOR": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 256,
+    "n_buckets": 50,
+    "description": "HPACK: Ratio of bytes evicted to bytes added (* 100)",
+    "alert_emails": ["necko@mozilla.com", "hurley@mozilla.com"],
+    "bug_numbers": [1296280]
+  },
+  "HPACK_PEAK_COUNT_COMPRESSOR": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 1024,
+    "n_buckets": 50,
+    "description": "HPACK: peak number of items in the dynamic table",
+    "alert_emails": ["necko@mozilla.com", "hurley@mozilla.com"],
+    "bug_numbers": [1296280]
+  },
+  "HPACK_PEAK_SIZE_COMPRESSOR": {
+    "expires_in_version": "never",
+    "kind": "exponential",
+    "high": 16384,
+    "n_buckets": 100,
+    "description": "HPACK: peak size in bytes of the table",
+    "alert_emails": ["necko@mozilla.com", "hurley@mozilla.com"],
+    "bug_numbers": [1296280]
+  },
   "HTTP_CONNECTION_ENTRY_CACHE_HIT_1" : {
     "expires_in_version": "never",
     "kind": "boolean",
     "description": "Fraction of sockets that used a nsConnectionEntry with history - size 300."
   },
   "HTTP_CACHE_DISPOSITION_2": {
     "expires_in_version": "never",
     "kind": "enumerated",