Bug 986082 - add memory reporters for SPDY zlib buffers; r=hurley,njn
authorNathan Froyd <froydnj@mozilla.com>
Thu, 20 Mar 2014 14:22:17 -0400
changeset 195118 2de3bb4941ed5d8fa43cf4913b12e51ee270c58f
parent 195117 ef3e291155ae4edf326a07c87f16d61ceabe983c
child 195119 5ad1392066742f19a0a9e63976d23378bfcccecb
push id486
push userasasaki@mozilla.com
push dateMon, 14 Jul 2014 18:39:42 +0000
treeherdermozilla-release@d33428174ff1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershurley, njn
bugs986082
milestone31.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 986082 - add memory reporters for SPDY zlib buffers; r=hurley,njn
netwerk/protocol/http/SpdySession3.cpp
netwerk/protocol/http/SpdySession31.cpp
netwerk/protocol/http/SpdyStream3.cpp
netwerk/protocol/http/SpdyStream3.h
netwerk/protocol/http/SpdyStream31.cpp
netwerk/protocol/http/SpdyStream31.h
netwerk/protocol/http/SpdyZlibReporter.cpp
netwerk/protocol/http/SpdyZlibReporter.h
netwerk/protocol/http/moz.build
netwerk/protocol/http/nsHttpHandler.cpp
--- a/netwerk/protocol/http/SpdySession3.cpp
+++ b/netwerk/protocol/http/SpdySession3.cpp
@@ -18,16 +18,17 @@
 #include "nsHttp.h"
 #include "nsHttpHandler.h"
 #include "nsILoadGroup.h"
 #include "prprf.h"
 #include "SpdyPush3.h"
 #include "SpdySession3.h"
 #include "SpdyStream3.h"
 #include "PSpdyPush.h"
+#include "SpdyZlibReporter.h"
 
 #include <algorithm>
 
 #ifdef DEBUG
 // defined by the socket transport service while active
 extern PRThread *gSocketThread;
 #endif
 
@@ -581,24 +582,24 @@ SpdySession3::DecrementConcurrent(SpdySt
   LOG3(("DecrementConcurrent %p id=0x%X concurrent=%d\n",
         this, id, mConcurrent));
   ProcessPending();
 }
 
 void
 SpdySession3::zlibInit()
 {
-  mDownstreamZlib.zalloc = SpdyStream3::zlib_allocator;
-  mDownstreamZlib.zfree = SpdyStream3::zlib_destructor;
+  mDownstreamZlib.zalloc = SpdyZlibReporter::Alloc;
+  mDownstreamZlib.zfree = SpdyZlibReporter::Free;
   mDownstreamZlib.opaque = Z_NULL;
 
   inflateInit(&mDownstreamZlib);
 
-  mUpstreamZlib.zalloc = SpdyStream3::zlib_allocator;
-  mUpstreamZlib.zfree = SpdyStream3::zlib_destructor;
+  mUpstreamZlib.zalloc = SpdyZlibReporter::Alloc;
+  mUpstreamZlib.zfree = SpdyZlibReporter::Free;
   mUpstreamZlib.opaque = Z_NULL;
 
   // mixing carte blanche compression with tls subjects us to traffic
   // analysis attacks
   deflateInit(&mUpstreamZlib, Z_NO_COMPRESSION);
   deflateSetDictionary(&mUpstreamZlib,
                        SpdyStream3::kDictionary,
                        sizeof(SpdyStream3::kDictionary));
--- a/netwerk/protocol/http/SpdySession31.cpp
+++ b/netwerk/protocol/http/SpdySession31.cpp
@@ -19,16 +19,17 @@
 #include "nsHttpHandler.h"
 #include "nsHttpConnection.h"
 #include "nsILoadGroup.h"
 #include "prprf.h"
 #include "prnetdb.h"
 #include "SpdyPush31.h"
 #include "SpdySession31.h"
 #include "SpdyStream31.h"
+#include "SpdyZlibReporter.h"
 
 #include <algorithm>
 
 #ifdef DEBUG
 // defined by the socket transport service while active
 extern PRThread *gSocketThread;
 #endif
 
@@ -586,24 +587,24 @@ SpdySession31::DecrementConcurrent(SpdyS
   LOG3(("DecrementConcurrent %p id=0x%X concurrent=%d\n",
         this, id, mConcurrent));
   ProcessPending();
 }
 
 void
 SpdySession31::zlibInit()
 {
-  mDownstreamZlib.zalloc = SpdyStream31::zlib_allocator;
-  mDownstreamZlib.zfree = SpdyStream31::zlib_destructor;
+  mDownstreamZlib.zalloc = SpdyZlibReporter::Alloc;
+  mDownstreamZlib.zfree = SpdyZlibReporter::Free;
   mDownstreamZlib.opaque = Z_NULL;
 
   inflateInit(&mDownstreamZlib);
 
-  mUpstreamZlib.zalloc = SpdyStream31::zlib_allocator;
-  mUpstreamZlib.zfree = SpdyStream31::zlib_destructor;
+  mUpstreamZlib.zalloc = SpdyZlibReporter::Alloc;
+  mUpstreamZlib.zfree = SpdyZlibReporter::Free;
   mUpstreamZlib.opaque = Z_NULL;
 
   // mixing carte blanche compression with tls subjects us to traffic
   // analysis attacks
   deflateInit(&mUpstreamZlib, Z_NO_COMPRESSION);
   deflateSetDictionary(&mUpstreamZlib,
                        SpdyStream31::kDictionary,
                        sizeof(SpdyStream31::kDictionary));
--- a/netwerk/protocol/http/SpdyStream3.cpp
+++ b/netwerk/protocol/http/SpdyStream3.cpp
@@ -20,16 +20,17 @@
 #include "nsHttpRequestHead.h"
 #include "nsISocketTransport.h"
 #include "nsISupportsPriority.h"
 #include "prnetdb.h"
 #include "SpdyPush3.h"
 #include "SpdySession3.h"
 #include "SpdyStream3.h"
 #include "PSpdyPush.h"
+#include "SpdyZlibReporter.h"
 
 #include <algorithm>
 
 #ifdef DEBUG
 // defined by the socket transport service while active
 extern PRThread *gSocketThread;
 #endif
 
@@ -981,30 +982,16 @@ const unsigned char SpdyStream3::kDictio
 	0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,   // c h c h a r s e
 	0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63,   // t - u t f - 8 c
 	0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69,   // h a r s e t - i
 	0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d,   // s o - 8 8 5 9 -
 	0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a,   // 1 - u t f - - -
 	0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e          // - e n q - 0 -
 };
 
-// use for zlib data types
-void *
-SpdyStream3::zlib_allocator(void *opaque, uInt items, uInt size)
-{
-  return moz_xmalloc(items * size);
-}
-
-// use for zlib data types
-void
-SpdyStream3::zlib_destructor(void *opaque, void *addr)
-{
-  moz_free(addr);
-}
-
 // This can be called N times.. 1 for syn_reply and 0->N for headers
 nsresult
 SpdyStream3::Uncompress(z_stream *context,
                         char *blockStart,
                         uint32_t blockLen)
 {
   mDecompressedBytes += blockLen;
 
--- a/netwerk/protocol/http/SpdyStream3.h
+++ b/netwerk/protocol/http/SpdyStream3.h
@@ -61,21 +61,18 @@ public:
   bool RecvdFin() { return mRecvdFin; }
 
   void SetRecvdData(bool aStatus) { mReceivedData = aStatus ? 1 : 0; }
   bool RecvdData() { return mReceivedData; }
 
   void UpdateTransportSendEvents(uint32_t count);
   void UpdateTransportReadEvents(uint32_t count);
 
-  // The zlib header compression dictionary defined by SPDY,
-  // and hooks to the mozilla allocator for zlib to use.
+  // The zlib header compression dictionary defined by SPDY.
   static const unsigned char kDictionary[1423];
-  static void *zlib_allocator(void *, uInt, uInt);
-  static void zlib_destructor(void *, void *);
 
   nsresult Uncompress(z_stream *, char *, uint32_t);
   nsresult ConvertHeaders(nsACString &);
 
   void UpdateRemoteWindow(int32_t delta);
   int64_t RemoteWindow() { return mRemoteWindow; }
 
   void DecrementLocalWindow(uint32_t delta) {
--- a/netwerk/protocol/http/SpdyStream31.cpp
+++ b/netwerk/protocol/http/SpdyStream31.cpp
@@ -998,30 +998,16 @@ const unsigned char SpdyStream31::kDicti
   0x63, 0x68, 0x63, 0x68, 0x61, 0x72, 0x73, 0x65,   // c h c h a r s e
   0x74, 0x3d, 0x75, 0x74, 0x66, 0x2d, 0x38, 0x63,   // t - u t f - 8 c
   0x68, 0x61, 0x72, 0x73, 0x65, 0x74, 0x3d, 0x69,   // h a r s e t - i
   0x73, 0x6f, 0x2d, 0x38, 0x38, 0x35, 0x39, 0x2d,   // s o - 8 8 5 9 -
   0x31, 0x2c, 0x75, 0x74, 0x66, 0x2d, 0x2c, 0x2a,   // 1 - u t f - - -
   0x2c, 0x65, 0x6e, 0x71, 0x3d, 0x30, 0x2e          // - e n q - 0 -
 };
 
-// use for zlib data types
-void *
-SpdyStream31::zlib_allocator(void *opaque, uInt items, uInt size)
-{
-  return moz_xmalloc(items * size);
-}
-
-// use for zlib data types
-void
-SpdyStream31::zlib_destructor(void *opaque, void *addr)
-{
-  moz_free(addr);
-}
-
 // This can be called N times.. 1 for syn_reply and 0->N for headers
 nsresult
 SpdyStream31::Uncompress(z_stream *context,
                          char *blockStart,
                          uint32_t blockLen)
 {
   mDecompressedBytes += blockLen;
 
--- a/netwerk/protocol/http/SpdyStream31.h
+++ b/netwerk/protocol/http/SpdyStream31.h
@@ -56,21 +56,18 @@ public:
   bool RecvdFin() { return mRecvdFin; }
 
   void SetRecvdData(bool aStatus) { mReceivedData = aStatus ? 1 : 0; }
   bool RecvdData() { return mReceivedData; }
 
   void UpdateTransportSendEvents(uint32_t count);
   void UpdateTransportReadEvents(uint32_t count);
 
-  // The zlib header compression dictionary defined by SPDY,
-  // and hooks to the mozilla allocator for zlib to use.
+  // The zlib header compression dictionary defined by SPDY.
   static const unsigned char kDictionary[1423];
-  static void *zlib_allocator(void *, uInt, uInt);
-  static void zlib_destructor(void *, void *);
 
   nsresult Uncompress(z_stream *, char *, uint32_t);
   nsresult ConvertHeaders(nsACString &);
 
   void UpdateRemoteWindow(int32_t delta);
   int64_t RemoteWindow() { return mRemoteWindow; }
 
   void DecrementLocalWindow(uint32_t delta) {
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/http/SpdyZlibReporter.cpp
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SpdyZlibReporter.h"
+
+namespace mozilla {
+
+NS_IMPL_ISUPPORTS1(SpdyZlibReporter, nsIMemoryReporter)
+
+/* static */ Atomic<size_t> SpdyZlibReporter::sAmount;
+
+/* static */ void*
+SpdyZlibReporter::Alloc(void*, uInt items, uInt size)
+{
+  void* p = moz_xmalloc(items * size);
+  sAmount += MallocSizeOfOnAlloc(p);
+  return p;
+}
+
+/* static */ void
+SpdyZlibReporter::Free(void*, void* p)
+{
+  sAmount -= MallocSizeOfOnFree(p);
+  moz_free(p);
+}
+
+NS_IMETHODIMP
+SpdyZlibReporter::CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData)
+{
+  return MOZ_COLLECT_REPORT(
+    "explicit/network/spdy-zlib-buffers", KIND_HEAP, UNITS_BYTES, sAmount,
+    "Memory allocated for SPDY zlib send and receive buffers.");
+}
+
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/netwerk/protocol/http/SpdyZlibReporter.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/* A memory allocator for zlib use in SPDY that reports to about:memory. */
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Atomics.h"
+#include "mozilla/Attributes.h"
+#include "nsIMemoryReporter.h"
+#include "zlib.h"
+
+namespace mozilla {
+
+class SpdyZlibReporter MOZ_FINAL : public nsIMemoryReporter
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  SpdyZlibReporter()
+  {
+#ifdef DEBUG
+    // There must be only one instance of this class, due to |sAmount|
+    // being static.
+    static bool hasRun = false;
+    MOZ_ASSERT(!hasRun);
+    hasRun = true;
+#endif
+    sAmount = 0;
+  }
+
+  static void* Alloc(void*, uInt items, uInt size);
+  static void Free(void*, void* p);
+
+private:
+  // |sAmount| can be (implicitly) accessed by multiple threads, so it
+  // must be thread-safe.
+  static Atomic<size_t> sAmount;
+
+  MOZ_DEFINE_MALLOC_SIZE_OF(MallocSizeOf)
+  MOZ_DEFINE_MALLOC_SIZE_OF_ON_ALLOC(MallocSizeOfOnAlloc)
+  MOZ_DEFINE_MALLOC_SIZE_OF_ON_FREE(MallocSizeOfOnFree)
+
+  NS_IMETHODIMP
+  CollectReports(nsIHandleReportCallback* aHandleReport, nsISupports* aData);
+};
+
+} // namespace mozilla
--- a/netwerk/protocol/http/moz.build
+++ b/netwerk/protocol/http/moz.build
@@ -72,16 +72,17 @@ SOURCES += [
     'nsHttpTransaction.cpp',
     'NullHttpTransaction.cpp',
     'SpdyPush3.cpp',
     'SpdyPush31.cpp',
     'SpdySession3.cpp',
     'SpdySession31.cpp',
     'SpdyStream3.cpp',
     'SpdyStream31.cpp',
+    'SpdyZlibReporter.cpp',
 ]
 
 # These files cannot be built in unified mode because of OS X headers.
 SOURCES += [
     'nsHttpHandler.cpp',
 ]
 
 IPDL_SOURCES += [
--- a/netwerk/protocol/http/nsHttpHandler.cpp
+++ b/netwerk/protocol/http/nsHttpHandler.cpp
@@ -40,16 +40,18 @@
 #include "nsIXULAppInfo.h"
 #include "nsICacheSession.h"
 #include "nsICookieService.h"
 #include "nsIObserverService.h"
 #include "nsISiteSecurityService.h"
 #include "nsIStreamConverterService.h"
 #include "nsITimer.h"
 #include "nsCRT.h"
+#include "SpdyZlibReporter.h"
+#include "nsIMemoryReporter.h"
 
 #include "mozilla/net/NeckoChild.h"
 #include "mozilla/Telemetry.h"
 
 #if defined(XP_UNIX)
 #include <sys/utsname.h>
 #endif
 
@@ -204,16 +206,18 @@ nsHttpHandler::nsHttpHandler()
     , mTCPKeepaliveLongLivedIdleTimeS(600)
 {
 #if defined(PR_LOGGING)
     gHttpLog = PR_NewLogModule("nsHttp");
 #endif
 
     LOG(("Creating nsHttpHandler [this=%p].\n", this));
 
+    RegisterStrongMemoryReporter(new SpdyZlibReporter());
+
     MOZ_ASSERT(!gHttpHandler, "HTTP handler already created!");
     gHttpHandler = this;
 }
 
 nsHttpHandler::~nsHttpHandler()
 {
     LOG(("Deleting nsHttpHandler [this=%p]\n", this));