зеркало из https://github.com/mozilla/gecko-dev.git
Backout db5eef36bcd9 (bug 1117825) for dt2 orange
This commit is contained in:
Родитель
e02d1f8242
Коммит
be4d564b24
|
@ -19,7 +19,6 @@ support-files =
|
||||||
[browser_flame-graph-02.js]
|
[browser_flame-graph-02.js]
|
||||||
[browser_flame-graph-03.js]
|
[browser_flame-graph-03.js]
|
||||||
[browser_flame-graph-04.js]
|
[browser_flame-graph-04.js]
|
||||||
[browser_flame-graph-utils.js]
|
|
||||||
[browser_graphs-01.js]
|
[browser_graphs-01.js]
|
||||||
[browser_graphs-02.js]
|
[browser_graphs-02.js]
|
||||||
[browser_graphs-03.js]
|
[browser_graphs-03.js]
|
||||||
|
|
|
@ -1,203 +0,0 @@
|
||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
// Tests that text metrics in the flame graph widget work properly.
|
|
||||||
|
|
||||||
let {FlameGraphUtils} = Cu.import("resource:///modules/devtools/FlameGraph.jsm", {});
|
|
||||||
|
|
||||||
let test = Task.async(function*() {
|
|
||||||
yield promiseTab("about:blank");
|
|
||||||
yield performTest();
|
|
||||||
gBrowser.removeCurrentTab();
|
|
||||||
finish();
|
|
||||||
});
|
|
||||||
|
|
||||||
function* performTest() {
|
|
||||||
let out = FlameGraphUtils.createFlameGraphDataFromSamples(TEST_DATA);
|
|
||||||
|
|
||||||
ok(out, "Some data was outputted properly");
|
|
||||||
is(out.length, 10, "The outputted length is correct.");
|
|
||||||
|
|
||||||
for (let i = 0; i < out.length; i++) {
|
|
||||||
let found = out[i];
|
|
||||||
let expected = EXPECTED_OUTPUT[i];
|
|
||||||
|
|
||||||
is(found.blocks.length, expected.blocks.length,
|
|
||||||
"The correct number of blocks were found in this bucket.");
|
|
||||||
|
|
||||||
for (let j = 0; j < found.blocks.length; j++) {
|
|
||||||
is(found.blocks[j].x, expected.blocks[j].x,
|
|
||||||
"The expected block X position is correct for this frame.");
|
|
||||||
is(found.blocks[j].y, expected.blocks[j].y,
|
|
||||||
"The expected block Y position is correct for this frame.");
|
|
||||||
is(found.blocks[j].width, expected.blocks[j].width,
|
|
||||||
"The expected block width is correct for this frame.");
|
|
||||||
is(found.blocks[j].height, expected.blocks[j].height,
|
|
||||||
"The expected block height is correct for this frame.");
|
|
||||||
is(found.blocks[j].text, expected.blocks[j].text,
|
|
||||||
"The expected block text is correct for this frame.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let TEST_DATA = [{
|
|
||||||
frames: [{
|
|
||||||
location: "M"
|
|
||||||
}, {
|
|
||||||
location: "N",
|
|
||||||
}, {
|
|
||||||
location: "P"
|
|
||||||
}],
|
|
||||||
time: 50,
|
|
||||||
}, {
|
|
||||||
frames: [{
|
|
||||||
location: "A"
|
|
||||||
}, {
|
|
||||||
location: "B",
|
|
||||||
}, {
|
|
||||||
location: "C"
|
|
||||||
}],
|
|
||||||
time: 100,
|
|
||||||
}, {
|
|
||||||
frames: [{
|
|
||||||
location: "A"
|
|
||||||
}, {
|
|
||||||
location: "B",
|
|
||||||
}, {
|
|
||||||
location: "D"
|
|
||||||
}],
|
|
||||||
time: 210,
|
|
||||||
}, {
|
|
||||||
frames: [{
|
|
||||||
location: "A"
|
|
||||||
}, {
|
|
||||||
location: "E",
|
|
||||||
}, {
|
|
||||||
location: "F"
|
|
||||||
}],
|
|
||||||
time: 330,
|
|
||||||
}, {
|
|
||||||
frames: [{
|
|
||||||
location: "A"
|
|
||||||
}, {
|
|
||||||
location: "B",
|
|
||||||
}, {
|
|
||||||
location: "C"
|
|
||||||
}],
|
|
||||||
time: 460,
|
|
||||||
}, {
|
|
||||||
frames: [{
|
|
||||||
location: "X"
|
|
||||||
}, {
|
|
||||||
location: "Y",
|
|
||||||
}, {
|
|
||||||
location: "Z"
|
|
||||||
}],
|
|
||||||
time: 500
|
|
||||||
}];
|
|
||||||
|
|
||||||
let EXPECTED_OUTPUT = [{
|
|
||||||
blocks: [{
|
|
||||||
x: 0,
|
|
||||||
y: 24,
|
|
||||||
width: 50,
|
|
||||||
height: 12,
|
|
||||||
text: "P"
|
|
||||||
}, {
|
|
||||||
x: 210,
|
|
||||||
y: 24,
|
|
||||||
width: 120,
|
|
||||||
height: 12,
|
|
||||||
text: "F"
|
|
||||||
}, {
|
|
||||||
x: 460,
|
|
||||||
y: 24,
|
|
||||||
width: 40,
|
|
||||||
height: 12,
|
|
||||||
text: "Z"
|
|
||||||
}]
|
|
||||||
}, {
|
|
||||||
blocks: []
|
|
||||||
}, {
|
|
||||||
blocks: []
|
|
||||||
}, {
|
|
||||||
blocks: []
|
|
||||||
}, {
|
|
||||||
blocks: []
|
|
||||||
}, {
|
|
||||||
blocks: [{
|
|
||||||
x: 50,
|
|
||||||
y: 0,
|
|
||||||
width: 410,
|
|
||||||
height: 12,
|
|
||||||
text: "A"
|
|
||||||
}]
|
|
||||||
}, {
|
|
||||||
blocks: [{
|
|
||||||
x: 50,
|
|
||||||
y: 12,
|
|
||||||
width: 160,
|
|
||||||
height: 12,
|
|
||||||
text: "B"
|
|
||||||
}, {
|
|
||||||
x: 330,
|
|
||||||
y: 12,
|
|
||||||
width: 130,
|
|
||||||
height: 12,
|
|
||||||
text: "B"
|
|
||||||
}]
|
|
||||||
}, {
|
|
||||||
blocks: [{
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: 50,
|
|
||||||
height: 12,
|
|
||||||
text: "M"
|
|
||||||
}, {
|
|
||||||
x: 50,
|
|
||||||
y: 24,
|
|
||||||
width: 50,
|
|
||||||
height: 12,
|
|
||||||
text: "C"
|
|
||||||
}, {
|
|
||||||
x: 330,
|
|
||||||
y: 24,
|
|
||||||
width: 130,
|
|
||||||
height: 12,
|
|
||||||
text: "C"
|
|
||||||
}]
|
|
||||||
}, {
|
|
||||||
blocks: [{
|
|
||||||
x: 0,
|
|
||||||
y: 12,
|
|
||||||
width: 50,
|
|
||||||
height: 12,
|
|
||||||
text: "N"
|
|
||||||
}, {
|
|
||||||
x: 100,
|
|
||||||
y: 24,
|
|
||||||
width: 110,
|
|
||||||
height: 12,
|
|
||||||
text: "D"
|
|
||||||
}, {
|
|
||||||
x: 460,
|
|
||||||
y: 0,
|
|
||||||
width: 40,
|
|
||||||
height: 12,
|
|
||||||
text: "X"
|
|
||||||
}]
|
|
||||||
}, {
|
|
||||||
blocks: [{
|
|
||||||
x: 210,
|
|
||||||
y: 12,
|
|
||||||
width: 120,
|
|
||||||
height: 12,
|
|
||||||
text: "E"
|
|
||||||
}, {
|
|
||||||
x: 460,
|
|
||||||
y: 12,
|
|
||||||
width: 40,
|
|
||||||
height: 12,
|
|
||||||
text: "Y"
|
|
||||||
}]
|
|
||||||
}];
|
|
|
@ -746,121 +746,10 @@ FlameGraph.prototype = {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const FLAME_GRAPH_BLOCK_HEIGHT = 12; // px
|
|
||||||
|
|
||||||
const PALLETTE_SIZE = 10;
|
|
||||||
const PALLETTE_HUE_OFFSET = Math.random() * 90;
|
|
||||||
const PALLETTE_HUE_RANGE = 270;
|
|
||||||
const PALLETTE_SATURATION = 60;
|
|
||||||
const PALLETTE_BRIGHTNESS = 75;
|
|
||||||
const PALLETTE_OPACITY = 0.7;
|
|
||||||
|
|
||||||
const COLOR_PALLETTE = Array.from(Array(PALLETTE_SIZE)).map((_, i) => "hsla" +
|
|
||||||
"(" + ((PALLETTE_HUE_OFFSET + (i / PALLETTE_SIZE * PALLETTE_HUE_RANGE))|0 % 360) +
|
|
||||||
"," + PALLETTE_SATURATION + "%" +
|
|
||||||
"," + PALLETTE_BRIGHTNESS + "%" +
|
|
||||||
"," + PALLETTE_OPACITY +
|
|
||||||
")"
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of utility functions converting various data sources
|
* A collection of utility functions converting various data sources
|
||||||
* into a format drawable by the FlameGraph.
|
* into a format drawable by the FlameGraph.
|
||||||
*/
|
*/
|
||||||
let FlameGraphUtils = {
|
let FlameGraphUtils = {
|
||||||
/**
|
// TODO bug 1077459
|
||||||
* Converts a list of samples from the profiler data to something that's
|
|
||||||
* drawable by a FlameGraph widget.
|
|
||||||
*
|
|
||||||
* @param array samples
|
|
||||||
* A list of { time, frames: [{ location }] } objects.
|
|
||||||
* @param array out [optional]
|
|
||||||
* An output storage to reuse for storing the flame graph data.
|
|
||||||
* @return array
|
|
||||||
* The flame graph data.
|
|
||||||
*/
|
|
||||||
createFlameGraphDataFromSamples: function(samples, out = []) {
|
|
||||||
// 1. Create a map of colors to arrays, representing buckets of
|
|
||||||
// blocks inside the flame graph pyramid sharing the same style.
|
|
||||||
|
|
||||||
let buckets = new Map();
|
|
||||||
|
|
||||||
for (let color of COLOR_PALLETTE) {
|
|
||||||
buckets.set(color, []);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Populate the buckets by iterating over every frame in every sample.
|
|
||||||
|
|
||||||
let prevTime = 0;
|
|
||||||
let prevFrames = [];
|
|
||||||
|
|
||||||
for (let { frames, time } of samples) {
|
|
||||||
let frameIndex = 0;
|
|
||||||
|
|
||||||
for (let { location } of frames) {
|
|
||||||
let prevFrame = prevFrames[frameIndex];
|
|
||||||
|
|
||||||
// Frames at the same location and the same depth will be reused.
|
|
||||||
// If there is a block already created, change its width.
|
|
||||||
if (prevFrame && prevFrame.srcData.rawLocation == location) {
|
|
||||||
prevFrame.width = (time - prevFrame.srcData.startTime);
|
|
||||||
}
|
|
||||||
// Otherwise, create a new block for this frame at this depth,
|
|
||||||
// using a simple location based salt for picking a color.
|
|
||||||
else {
|
|
||||||
let salt = this._getStringHash(location);
|
|
||||||
let color = COLOR_PALLETTE[salt % PALLETTE_SIZE];
|
|
||||||
let bucket = buckets.get(color);
|
|
||||||
|
|
||||||
bucket.push(prevFrames[frameIndex] = {
|
|
||||||
srcData: { startTime: prevTime, rawLocation: location },
|
|
||||||
x: prevTime,
|
|
||||||
y: frameIndex * FLAME_GRAPH_BLOCK_HEIGHT,
|
|
||||||
width: time - prevTime,
|
|
||||||
height: FLAME_GRAPH_BLOCK_HEIGHT,
|
|
||||||
text: location
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
frameIndex++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Previous frames at stack depths greater than the current sample's
|
|
||||||
// maximum need to be nullified. It's nonsensical to reuse them.
|
|
||||||
for (let i = frameIndex; i < prevFrames.length; i++) {
|
|
||||||
prevFrames[i] = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
prevTime = time;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Convert the buckets into a data source usable by the FlameGraph.
|
|
||||||
// This is a simple conversion from a Map to an Array.
|
|
||||||
|
|
||||||
for (let [color, blocks] of buckets) {
|
|
||||||
out.push({ color, blocks });
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Very dumb hashing of a string. Used to pick colors from a pallette.
|
|
||||||
*
|
|
||||||
* @param string input
|
|
||||||
* @return number
|
|
||||||
*/
|
|
||||||
_getStringHash: function(input) {
|
|
||||||
const STRING_HASH_PRIME1 = 7;
|
|
||||||
const STRING_HASH_PRIME2 = 31;
|
|
||||||
|
|
||||||
let hash = STRING_HASH_PRIME1;
|
|
||||||
|
|
||||||
for (let i = 0, len = input.length; i < len; i++) {
|
|
||||||
hash *= STRING_HASH_PRIME2;
|
|
||||||
hash += input.charCodeAt(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче