bug 1218576 - Request an immediate batch send when the batch size hits a high water mark. r=gfritzsche
authorChris H-C <chutten@mozilla.com>
Thu, 08 Sep 2016 10:15:15 -0400
changeset 314454 ca430b715311
parent 314453 1b498933da3a
child 314455 5a20e1ffb8ea
push id20574
push usercbook@mozilla.com
push dateTue, 20 Sep 2016 10:05:16 +0000
treeherderfx-team@14705f779a46 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgfritzsche
bugs1218576
milestone51.0a1
bug 1218576 - Request an immediate batch send when the batch size hits a high water mark. r=gfritzsche We've now seen an OOM trying to grow the accumulations array during a test suite. The g*Accumulations arrays do grow unboundedly in size waiting for the IPC timer to fire, so we should put a size bound as well as a time bound to trigger the batch send. The current size bound is 5K elements. This was chosen out of a hat. MozReview-Commit-ID: 5HeWdbLfN03
toolkit/components/telemetry/TelemetryHistogram.cpp
--- a/toolkit/components/telemetry/TelemetryHistogram.cpp
+++ b/toolkit/components/telemetry/TelemetryHistogram.cpp
@@ -220,16 +220,21 @@ const mozilla::Telemetry::ID kRecordingI
 };
 
 // Sending each remote accumulation immediately places undue strain on the
 // IPC subsystem. Batch the remote accumulations for a period of time before
 // sending them all at once. This value was chosen as a balance between data
 // timeliness and performance (see bug 1218576)
 const uint32_t kBatchTimeoutMs = 2000;
 
+// To stop growing unbounded in memory while waiting for kBatchTimeoutMs to
+// drain the g*Accumulations arrays, request an immediate flush if the arrays
+// manage to reach this high water mark of elements.
+const size_t kAccumulationsArrayHighWaterMark = 5 * 1024;
+
 } // namespace
 
 
 ////////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////////
 //
 // PRIVATE: Misc small helpers
 
@@ -1310,31 +1315,41 @@ bool
 internal_RemoteAccumulate(mozilla::Telemetry::ID aId, uint32_t aSample)
 {
   if (XRE_IsParentProcess()) {
     return false;
   }
   if (!gAccumulations) {
     gAccumulations = new nsTArray<Accumulation>();
   }
+  if (gAccumulations->Length() == kAccumulationsArrayHighWaterMark) {
+    NS_DispatchToMainThread(NS_NewRunnableFunction([]() -> void {
+      TelemetryHistogram::IPCTimerFired(nullptr, nullptr);
+    }));
+  }
   gAccumulations->AppendElement(Accumulation{aId, aSample});
   internal_armIPCTimer();
   return true;
 }
 
 bool
 internal_RemoteAccumulate(mozilla::Telemetry::ID aId,
                     const nsCString& aKey, uint32_t aSample)
 {
   if (XRE_IsParentProcess()) {
     return false;
   }
   if (!gKeyedAccumulations) {
     gKeyedAccumulations = new nsTArray<KeyedAccumulation>();
   }
+  if (gKeyedAccumulations->Length() == kAccumulationsArrayHighWaterMark) {
+    NS_DispatchToMainThread(NS_NewRunnableFunction([]() -> void {
+      TelemetryHistogram::IPCTimerFired(nullptr, nullptr);
+    }));
+  }
   gKeyedAccumulations->AppendElement(KeyedAccumulation{aId, aSample, aKey});
   internal_armIPCTimer();
   return true;
 }
 
 void internal_Accumulate(mozilla::Telemetry::ID aHistogram, uint32_t aSample)
 {
   bool isValid = internal_IsHistogramEnumId(aHistogram);