Bug 1296280 (part 1) - Add telemetry for HPACK usage. r?mcmanus data-review=bsmedberg
MozReview-Commit-ID: Hk5XNrj3Tbh
--- 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",