Bug 1241362: about:telemetry - fix thread hangs histograms buckets+labels. r=chutten
authorAvi Halachmi <avihpit@yahoo.com>
Mon, 25 Jan 2016 20:43:09 +0200
changeset 281556 4f708fbffedef3826c8c3ea861f125e6b6c7c30e
parent 281555 1b7625c90538a95413f7ca1910f4ec791eff82b5
child 281557 03d8d969187ad8d3e8e73a79727ccddd3dec4f4e
push id29946
push usercbook@mozilla.com
push dateTue, 26 Jan 2016 10:53:45 +0000
treeherdermozilla-central@c0ba5835ca48 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerschutten
bugs1241362
milestone46.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 1241362: about:telemetry - fix thread hangs histograms buckets+labels. r=chutten
toolkit/content/aboutTelemetry.js
--- a/toolkit/content/aboutTelemetry.js
+++ b/toolkit/content/aboutTelemetry.js
@@ -1121,21 +1121,21 @@ var ThreadHangStats = {
 
     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});
+                     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});
+        div, hangName, hang.histogram, {exponential: true}, true);
       let stackDiv = document.createElement("div");
       let stack = hang.nativeStack || hang.stack;
       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
@@ -1158,20 +1158,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));
@@ -1202,17 +1203,17 @@ var Histogram = {
                                                  .copyString(this.histogramText);
     });
     outerDiv.appendChild(copyButton);
 
     aParent.appendChild(outerDiv);
     return outerDiv;
   },
 
-  processHistogram: function(aHgram, aName) {
+  processHistogram: function(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,
@@ -1220,17 +1221,37 @@ 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);
 
-    const labelledValues = Object.keys(aHgram.values).map(k => [Number(k), aHgram.values[k]]);
+    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, ...
+      return !aIsBHR ? k : k == 1 ? 0 : (k + 1) / 2;
+    }
+
+    const labelledValues = Object.keys(aHgram.values)
+                           .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: sample_count,
       sum: aHgram.sum
     };