Backed out changeset b1fdf3c9f074 (bug 1380081)
authorSebastian Hengst <archaeopteryx@coole-files.de>
Fri, 11 Aug 2017 09:28:52 +0200
changeset 374269 e6d57bb2b33e6b37585b44e0bfd3f76d45f808d2
parent 374268 f6b47124336fba85e8ba753ae607c2347b5665e6
child 374270 2145dba678d8f69a35149a120908445e55f02587
push id32318
push userkwierso@gmail.com
push dateFri, 11 Aug 2017 20:16:01 +0000
treeherdermozilla-central@80ff3f300e05 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1380081
milestone57.0a1
backs outb1fdf3c9f0742ec695aacf3fc14c48a6bd0c5df0
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
Backed out changeset b1fdf3c9f074 (bug 1380081)
toolkit/content/aboutTelemetry.js
toolkit/content/aboutTelemetry.xhtml
toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
--- a/toolkit/content/aboutTelemetry.js
+++ b/toolkit/content/aboutTelemetry.js
@@ -1124,16 +1124,67 @@ var CapturedStacks = {
 
   renderCaptureHeader: function CaptureStacks_renderCaptureHeader(index, captures) {
     let key = captures[index][0];
     let cardinality = captures[index][2];
     StackRenderer.renderHeader("captured-stacks", [key, cardinality]);
   }
 };
 
+var ThreadHangStats = {
+
+  /**
+   * Renders raw thread hang stats data
+   */
+  render(aPayload) {
+    let div = document.getElementById("thread-hang-stats");
+    removeAllChildNodes(div);
+
+    let stats = aPayload.threadHangStats;
+    setHasData("thread-hang-stats-section", stats && (stats.length > 0));
+    if (!stats) {
+      return;
+    }
+
+    stats.forEach((thread) => {
+      div.appendChild(this.renderThread(thread));
+    });
+  },
+
+  /**
+   * Creates and fills data corresponding to a thread
+   */
+  renderThread(aThread) {
+    let div = document.createElement("div");
+
+    let title = document.createElement("h2");
+    title.textContent = aThread.name;
+    div.appendChild(title);
+
+    // Don't localize the histogram name, because the
+    // name is also used as the div element's ID
+    Histogram.render(div, aThread.name + "-Activity",
+                     aThread.activity, {exponential: true}, true);
+    aThread.hangs.forEach((hang, index) => {
+      let hangName = aThread.name + "-Hang-" + (index + 1);
+      let hangDiv = Histogram.render(
+        div, hangName, hang.histogram, {exponential: true}, true);
+      let stackDiv = document.createElement("div");
+      hang.stack.forEach((frame) => {
+        stackDiv.appendChild(document.createTextNode(frame));
+        // Leave an extra <br> at the end of the stack listing
+        stackDiv.appendChild(document.createElement("br"));
+      });
+      // Insert stack after the histogram title
+      hangDiv.insertBefore(stackDiv, hangDiv.childNodes[1]);
+    });
+    return div;
+  },
+};
+
 var Histogram = {
 
   hgramSamplesCaption: bundle.GetStringFromName("histogramSamples"),
 
   hgramAverageCaption: bundle.GetStringFromName("histogramAverage"),
 
   hgramSumCaption: bundle.GetStringFromName("histogramSum"),
 
@@ -1142,20 +1193,21 @@ var Histogram = {
   /**
    * Renders a single Telemetry histogram
    *
    * @param aParent Parent element
    * @param aName Histogram name
    * @param aHgram Histogram information
    * @param aOptions Object with render options
    *                 * exponential: bars follow logarithmic scale
+   * @param aIsBHR whether or not requires fixing the labels for TimeHistogram
    */
-  render: function Histogram_render(aParent, aName, aHgram, aOptions) {
+  render: function Histogram_render(aParent, aName, aHgram, aOptions, aIsBHR) {
     let options = aOptions || {};
-    let hgram = this.processHistogram(aHgram, aName);
+    let hgram = this.processHistogram(aHgram, aName, aIsBHR);
 
     let outerDiv = document.createElement("div");
     outerDiv.className = "histogram";
     outerDiv.id = aName;
 
     let divTitle = document.createElement("div");
     divTitle.className = "histogram-title";
     divTitle.appendChild(document.createTextNode(aName));
@@ -1186,17 +1238,17 @@ var Histogram = {
                                                  .copyString(this.histogramText);
     });
     outerDiv.appendChild(copyButton);
 
     aParent.appendChild(outerDiv);
     return outerDiv;
   },
 
-  processHistogram(aHgram, aName) {
+  processHistogram(aHgram, aName, aIsBHR) {
     const values = Object.keys(aHgram.values).map(k => aHgram.values[k]);
     if (!values.length) {
       // If we have no values collected for this histogram, just return
       // zero values so we still render it.
       return {
         values: [],
         pretty_average: 0,
         max: 0,
@@ -1204,18 +1256,40 @@ var Histogram = {
         sum: 0
       };
     }
 
     const sample_count = values.reduceRight((a, b) => a + b);
     const average = Math.round(aHgram.sum * 10 / sample_count) / 10;
     const max_value = Math.max(...values);
 
+    function labelFunc(k) {
+      // - BHR histograms are TimeHistograms: Exactly power-of-two buckets (from 0)
+      //   (buckets: [0..1], [2..3], [4..7], [8..15], ... note the 0..1 anomaly - same bucket)
+      // - TimeHistogram's JS representation adds a dummy (empty) "0" bucket, and
+      //   the rest of the buckets have the label as the upper value of the
+      //   bucket (non TimeHistograms have the lower value of the bucket as label).
+      //   So JS TimeHistograms bucket labels are: 0 (dummy), 1, 3, 7, 15, ...
+      // - see toolkit/components/telemetry/Telemetry.cpp
+      //   (CreateJSTimeHistogram, CreateJSThreadHangStats, CreateJSHangHistogram)
+      // - see toolkit/components/telemetry/ThreadHangStats.h
+      // Fix BHR labels to the "standard" format for about:telemetry as follows:
+      //   - The dummy 0 label+bucket will be filtered before arriving here
+      //   - If it's 1 -> manually correct it to 0 (the 0..1 anomaly)
+      //   - For the rest, set the label as the bottom value instead of the upper.
+      //   --> so we'll end with the following (non dummy) labels: 0, 2, 4, 8, 16, ...
+      if (!aIsBHR) {
+        return k;
+      }
+      return k == 1 ? 0 : (k + 1) / 2;
+    }
+
     const labelledValues = Object.keys(aHgram.values)
-                           .map(k => [Number(k), aHgram.values[k]]);
+                           .filter(label => !aIsBHR || Number(label) != 0) // remove dummy 0 label for BHR
+                           .map(k => [labelFunc(Number(k)), aHgram.values[k]]);
 
     let result = {
       values: labelledValues,
       pretty_average: average,
       max: max_value,
       sample_count,
       sum: aHgram.sum
     };
@@ -2304,14 +2378,17 @@ function displayRichPingData(ping, updat
   }
 
   // Show chrome hang stacks
   ChromeHangs.render(payload);
 
   // Show telemetry log.
   TelLog.render(payload);
 
+  // Show thread hang stats
+  ThreadHangStats.render(payload);
+
   // Show simple measurements
   SimpleMeasurements.render(payload);
 
 }
 
 window.addEventListener("load", onLoad);
--- a/toolkit/content/aboutTelemetry.xhtml
+++ b/toolkit/content/aboutTelemetry.xhtml
@@ -67,16 +67,19 @@
         <span class="category-name">&aboutTelemetry.telemetryLogSection;</span>
       </div>
       <div class="category" value="slow-sql-section">
         <span class="category-name">&aboutTelemetry.slowSqlSection;</span>
       </div>
       <div class="category" value="chrome-hangs-section">
         <span class="category-name">&aboutTelemetry.chromeHangsSection;</span>
       </div>
+      <div class="category" value="thread-hang-stats-section">
+        <span class="category-name">&aboutTelemetry.threadHangStatsSection;</span>
+      </div>
       <div class="category" value="late-writes-section">
         <span class="category-name">&aboutTelemetry.lateWritesSection;</span>
       </div>
       <div class="category" value="addon-details-section">
         <span class="category-name">&aboutTelemetry.addonDetailsSection;</span>
       </div>
       <div class="category" value="captured-stacks-section">
         <span class="category-name">&aboutTelemetry.capturedStacksSection;</span>
@@ -196,16 +199,20 @@
           <a id="chrome-hangs-hide-symbols" class="hidden" href="">&aboutTelemetry.hideStackSymbols;</a>
           <br/>
           <br/>
           <div id="chrome-hangs-data">
           </div>
         </div>
       </section>
 
+      <section id="thread-hang-stats-section">
+        <div id="thread-hang-stats" class="data"></div>
+      </section>
+
       <section id="late-writes-section">
         <div id="late-writes" class="data">
           <a id="late-writes-fetch-symbols" href="">&aboutTelemetry.fetchStackSymbols;</a>
           <a id="late-writes-hide-symbols" class="hidden" href="">&aboutTelemetry.hideStackSymbols;</a>
           <br/>
           <br/>
           <div id="late-writes-data">
           </div>
--- a/toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
+++ b/toolkit/locales/en-US/chrome/global/aboutTelemetry.dtd
@@ -75,16 +75,20 @@ Older
 <!ENTITY aboutTelemetry.slowSqlSection "
   Slow SQL Statements
 ">
 
 <!ENTITY aboutTelemetry.chromeHangsSection "
   Browser Hangs
 ">
 
+<!ENTITY aboutTelemetry.threadHangStatsSection "
+  Thread Hangs
+">
+
 <!ENTITY aboutTelemetry.capturedStacksSection "
   Captured Stacks
 ">
 
 <!ENTITY aboutTelemetry.scalarsSection "
   Scalars
 ">