Bug 1211411 - Limit the number of thread hang stats reported to Telemetry. r=vladan a=lizzard
authorAlessio Placitelli <alessio.placitelli@gmail.com>
Fri, 16 Oct 2015 07:04:00 +0200
changeset 296722 59e6a978773f
parent 296721 2fd90a7f326e
child 296723 12762fdf5ab6
push id5308
push uservdjeric@mozilla.com
push date2015-11-15 23:58 +0000
treeherdermozilla-beta@aaa5100e2085 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvladan, lizzard
bugs1211411
milestone43.0
Bug 1211411 - Limit the number of thread hang stats reported to Telemetry. r=vladan a=lizzard
xpcom/threads/BackgroundHangMonitor.cpp
--- a/xpcom/threads/BackgroundHangMonitor.cpp
+++ b/xpcom/threads/BackgroundHangMonitor.cpp
@@ -26,16 +26,28 @@
 #include "mozilla/Services.h"
 #include "nsXULAppAPI.h"
 
 #include <algorithm>
 
 // Activate BHR only for one every BHR_BETA_MOD users.
 #define BHR_BETA_MOD 100;
 
+// Maximum depth of the call stack in the reported thread hangs. This value represents
+// the 95th pecentile of the thread hangs stack depths reported by Telemetry.
+static const size_t kMaxThreadHangStackDepth = 11;
+
+// An utility comparator function used by std::unique to collapse "(* script)" entries in
+// a vector representing a call stack.
+bool StackScriptEntriesCollapser(const char* aStackEntry, const char *aAnotherStackEntry)
+{
+  return !strcmp(aStackEntry, aAnotherStackEntry) &&
+         (!strcmp(aStackEntry, "(chrome script)") || !strcmp(aStackEntry, "(content script)"));
+}
+
 namespace mozilla {
 
 /**
  * BackgroundHangManager is the global object that
  * manages all instances of BackgroundHangThread.
  */
 class BackgroundHangManager : public nsIObserver
 {
@@ -393,16 +405,30 @@ BackgroundHangThread::ReportHang(PRInter
 
   // Remove unwanted "js::RunScript" frame from the stack
   for (const char** f = &mHangStack.back(); f >= mHangStack.begin(); f--) {
     if (!mHangStack.IsInBuffer(*f) && !strcmp(*f, "js::RunScript")) {
       mHangStack.erase(f);
     }
   }
 
+  // Collapse duplicated "(chrome script)" and "(content script)" entries in the stack.
+  auto it = std::unique(mHangStack.begin(), mHangStack.end(), StackScriptEntriesCollapser);
+  mHangStack.erase(it, mHangStack.end());
+
+  // Limit the depth of the reported stack if greater than our limit. Only keep its
+  // last entries, since the most recent frames are at the end of the vector.
+  if (mHangStack.length() > kMaxThreadHangStackDepth) {
+    const int elementsToRemove = mHangStack.length() - kMaxThreadHangStackDepth;
+    // Replace the oldest frame with a known label so that we can tell this stack
+    // was limited.
+    mHangStack[0] = "(reduced stack)";
+    mHangStack.erase(mHangStack.begin() + 1, mHangStack.begin() + elementsToRemove);
+  }
+
   Telemetry::HangHistogram newHistogram(Move(mHangStack));
   for (Telemetry::HangHistogram* oldHistogram = mStats.mHangs.begin();
        oldHistogram != mStats.mHangs.end(); oldHistogram++) {
     if (newHistogram == *oldHistogram) {
       // New histogram matches old one
       oldHistogram->Add(aHangTime, Move(mAnnotations));
       return *oldHistogram;
     }