mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
b9843e0358
- Bug 1167459 - Skip rendering function name nodes if there's no name available (e.g. for C++ pseudoframes), r=jsantell (4a69ed224)
- missing bits Bug 1102219 - Part 4: Replace String.prototype.contains with `String.prototype.includes` in chrome code. r=till (73cd2d2b1)
- Bug 1165045 - Don't create nodes with empty text in the call tree, r=jsantell (b013aa82d)
- Bug 1166122 - Fix regression in the call tree caused by bug 1165045, r=jsantell (ee3f16901)
- Bug 1167975 - CallView._displaySelf sets this.document just because other functions use it; it should pass it as an argument instead, r=jsantell (5ef560c4f)
- Bug 1122662 - Resize graphs when window resizes;r=vporof (25c108e4e)
- Bug 1164784 - Eliminate CSS duplication with perf tool record button r=jsantell (43c9bb999)
- Bug 1150761 - Rename the performance tool's details view names to better describe the data visualizations. r=vp (04ceb6a37)
- Bug 1144424 - Rename '{self,total} allocations' to '{self,total} sampled allocations' in the performance tool. r=jsantell (ae79ad54f)
- Bug 1069910 - Add tooltips explaining what each column in the profiler's tree view represents; r=jsantell (8756f88b6)
- Bug 1107849 - Define a min/max width for the performance panel sidebar. r=vporof (e1769e831)
- Bug 11663354 - A locked recording button should appear disabled in the performance tool. r=vp (4a359d39e)
- Bug 1023546 - DevTools - Support HDPI resolutions for Windows. r=bgrins (ef1a3ecb8)
- Bug 1168125 - Cleanup performance xul and css, r=jsantell (8ec794e46)
- Bug 1168125 - Replace the waterfall view with a tree, r=jsantell (ea76514fe)
- Bug 1168125 - Add marker folding logic, r=jsantell (1d3748d2a)
- Bug 862341 Part 1: Move the network request storage from the console frontend to the console client so the netmonitor can reuse it. r=vporof (d29fb2b73)
- remove gre from resource path (126b00df1)
- Bug 943306 - Allow persisting console input history between sessions;r=past (146ebb486)
- Bug 1134845 - Add clearHistory jsterm helper to remove persisted console input history. r=past (22237e95b)
- Bug 1143497 - Offer a way to extend WebConsole commands. r=bgrins (84e2d2957)
- Bug 1125205 - Display console API messages from shared or service workers to the web console, r=past (b4b701a2c)
- Bug 1169342 - Remove nsIDOMDeviceStorage. Cleanup nsDOMDeviceStorage event wrappers. r=dhylands (41338e16f)
- Bug 1151610 - Manage the case where two extensions fight over the same command. r=bgrins (63f9d2064)
- Bug 862341 Part 2: Display cached network requests in the web console. r=vporof (83c0e7263)
- Bug 1144211 - Improve code coverage of camera mochitests. r=mikeh (ba9f3de89)
- Bug 1152500 - Fix how stop recording may be handled out-of-order. r=dhylands (d8bdd379c)
- Bug 862341 Part 3: Display cached network requests in the network panel. r=vporof (a1a6f151d)
- Bug 862341 Part 4: Start recording network requests when the toolbox opens. r=vporof (7a2bdf847)
- Bug 1151499 - Correct the FM playable state. r=baku (8af26fff2)
- Bug 1180347 - Split media.useAudioChannelService to support turning the service on without turning the Firefox OS specific APIs on; r=baku (3fa29291a)
- Bug 862341 Part 5: Tests. r=vporof (82fb944c6)
188 lines
6.0 KiB
JavaScript
188 lines
6.0 KiB
JavaScript
/* 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/. */
|
|
"use strict";
|
|
|
|
/**
|
|
* This file contains the "waterfall ticks" view, a header for the
|
|
* markers displayed in the waterfall.
|
|
*/
|
|
|
|
loader.lazyRequireGetter(this, "L10N",
|
|
"devtools/performance/global", true);
|
|
loader.lazyRequireGetter(this, "WATERFALL_MARKER_SIDEBAR_WIDTH",
|
|
"devtools/performance/marker-view", true);
|
|
|
|
const HTML_NS = "http://www.w3.org/1999/xhtml";
|
|
|
|
const FIND_OPTIMAL_TICK_INTERVAL_MAX_ITERS = 100;
|
|
|
|
const WATERFALL_HEADER_TICKS_MULTIPLE = 5; // ms
|
|
const WATERFALL_HEADER_TICKS_SPACING_MIN = 50; // px
|
|
const WATERFALL_HEADER_TEXT_PADDING = 3; // px
|
|
|
|
const WATERFALL_BACKGROUND_TICKS_MULTIPLE = 5; // ms
|
|
const WATERFALL_BACKGROUND_TICKS_SCALES = 3;
|
|
const WATERFALL_BACKGROUND_TICKS_SPACING_MIN = 10; // px
|
|
const WATERFALL_BACKGROUND_TICKS_COLOR_RGB = [128, 136, 144];
|
|
const WATERFALL_BACKGROUND_TICKS_OPACITY_MIN = 32; // byte
|
|
const WATERFALL_BACKGROUND_TICKS_OPACITY_ADD = 32; // byte
|
|
|
|
/**
|
|
* A header for a markers waterfall.
|
|
*
|
|
* @param MarkerView root
|
|
* The root item of the waterfall tree.
|
|
*/
|
|
function WaterfallHeader(root) {
|
|
this.root = root;
|
|
}
|
|
|
|
WaterfallHeader.prototype = {
|
|
/**
|
|
* Creates and appends this header as the first element of the specified
|
|
* parent element.
|
|
*
|
|
* @param nsIDOMNode parentNode
|
|
* The parent element for this header.
|
|
*/
|
|
attachTo: function(parentNode) {
|
|
let document = parentNode.ownerDocument;
|
|
let startTime = this.root.interval.startTime;
|
|
let dataScale = this.root.getDataScale();
|
|
let waterfallWidth = this.root.getWaterfallWidth();
|
|
|
|
let header = this._buildNode(document, startTime, dataScale, waterfallWidth);
|
|
parentNode.insertBefore(header, parentNode.firstChild);
|
|
|
|
this._drawWaterfallBackground(document, dataScale, waterfallWidth);
|
|
},
|
|
|
|
/**
|
|
* Creates the node displaying this view.
|
|
*/
|
|
_buildNode: function(doc, startTime, dataScale, waterfallWidth) {
|
|
let container = doc.createElement("hbox");
|
|
container.className = "waterfall-header-container";
|
|
container.setAttribute("flex", "1");
|
|
|
|
let sidebar = doc.createElement("hbox");
|
|
sidebar.className = "waterfall-sidebar theme-sidebar";
|
|
sidebar.setAttribute("width", WATERFALL_MARKER_SIDEBAR_WIDTH);
|
|
sidebar.setAttribute("align", "center");
|
|
container.appendChild(sidebar);
|
|
|
|
let name = doc.createElement("description");
|
|
name.className = "plain waterfall-header-name";
|
|
name.setAttribute("value", L10N.getStr("timeline.records"));
|
|
sidebar.appendChild(name);
|
|
|
|
let ticks = doc.createElement("hbox");
|
|
ticks.className = "waterfall-header-ticks waterfall-background-ticks";
|
|
ticks.setAttribute("align", "center");
|
|
ticks.setAttribute("flex", "1");
|
|
container.appendChild(ticks);
|
|
|
|
let tickInterval = findOptimalTickInterval({
|
|
ticksMultiple: WATERFALL_HEADER_TICKS_MULTIPLE,
|
|
ticksSpacingMin: WATERFALL_HEADER_TICKS_SPACING_MIN,
|
|
dataScale: dataScale
|
|
});
|
|
|
|
for (let x = 0; x < waterfallWidth; x += tickInterval) {
|
|
let left = x + WATERFALL_HEADER_TEXT_PADDING;
|
|
let time = Math.round(x / dataScale + startTime);
|
|
let label = L10N.getFormatStr("timeline.tick", time);
|
|
|
|
let node = doc.createElement("description");
|
|
node.className = "plain waterfall-header-tick";
|
|
node.style.transform = "translateX(" + left + "px)";
|
|
node.setAttribute("value", label);
|
|
ticks.appendChild(node);
|
|
}
|
|
|
|
return container;
|
|
},
|
|
|
|
/**
|
|
* Creates the background displayed on the marker's waterfall.
|
|
*/
|
|
_drawWaterfallBackground: function(doc, dataScale, waterfallWidth) {
|
|
if (!this._canvas || !this._ctx) {
|
|
this._canvas = doc.createElementNS(HTML_NS, "canvas");
|
|
this._ctx = this._canvas.getContext("2d");
|
|
}
|
|
let canvas = this._canvas;
|
|
let ctx = this._ctx;
|
|
|
|
// Nuke the context.
|
|
let canvasWidth = canvas.width = waterfallWidth;
|
|
let canvasHeight = canvas.height = 1; // Awww yeah, 1px, repeats on Y axis.
|
|
|
|
// Start over.
|
|
let imageData = ctx.createImageData(canvasWidth, canvasHeight);
|
|
let pixelArray = imageData.data;
|
|
|
|
let buf = new ArrayBuffer(pixelArray.length);
|
|
let view8bit = new Uint8ClampedArray(buf);
|
|
let view32bit = new Uint32Array(buf);
|
|
|
|
// Build new millisecond tick lines...
|
|
let [r, g, b] = WATERFALL_BACKGROUND_TICKS_COLOR_RGB;
|
|
let alphaComponent = WATERFALL_BACKGROUND_TICKS_OPACITY_MIN;
|
|
let tickInterval = findOptimalTickInterval({
|
|
ticksMultiple: WATERFALL_BACKGROUND_TICKS_MULTIPLE,
|
|
ticksSpacingMin: WATERFALL_BACKGROUND_TICKS_SPACING_MIN,
|
|
dataScale: dataScale
|
|
});
|
|
|
|
// Insert one pixel for each division on each scale.
|
|
for (let i = 1; i <= WATERFALL_BACKGROUND_TICKS_SCALES; i++) {
|
|
let increment = tickInterval * Math.pow(2, i);
|
|
for (let x = 0; x < canvasWidth; x += increment) {
|
|
let position = x | 0;
|
|
view32bit[position] = (alphaComponent << 24) | (b << 16) | (g << 8) | r;
|
|
}
|
|
alphaComponent += WATERFALL_BACKGROUND_TICKS_OPACITY_ADD;
|
|
}
|
|
|
|
// Flush the image data and cache the waterfall background.
|
|
pixelArray.set(view8bit);
|
|
ctx.putImageData(imageData, 0, 0);
|
|
doc.mozSetImageElement("waterfall-background", canvas);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Finds the optimal tick interval between time markers in this timeline.
|
|
*
|
|
* @param number ticksMultiple
|
|
* @param number ticksSpacingMin
|
|
* @param number dataScale
|
|
* @return number
|
|
*/
|
|
function findOptimalTickInterval({ ticksMultiple, ticksSpacingMin, dataScale }) {
|
|
let timingStep = ticksMultiple;
|
|
let maxIters = FIND_OPTIMAL_TICK_INTERVAL_MAX_ITERS;
|
|
let numIters = 0;
|
|
|
|
if (dataScale > ticksSpacingMin) {
|
|
return dataScale;
|
|
}
|
|
|
|
while (true) {
|
|
let scaledStep = dataScale * timingStep;
|
|
if (++numIters > maxIters) {
|
|
return scaledStep;
|
|
}
|
|
if (scaledStep < ticksSpacingMin) {
|
|
timingStep <<= 1;
|
|
continue;
|
|
}
|
|
return scaledStep;
|
|
}
|
|
}
|
|
|
|
exports.WaterfallHeader = WaterfallHeader;
|
|
exports.TickUtils = { findOptimalTickInterval };
|