Bug 1194458 - Calculate bytesize costs per frame for allocations in the performance tools. r=vp,shu

--HG--
rename : browser/devtools/performance/test/browser_perf-allocations-to-samples.js => browser/devtools/performance/test/unit/test_perf-utils-allocations-to-samples.js
This commit is contained in:
Jordan Santell 2015-08-19 18:04:50 -07:00
Родитель 5de13ebb49
Коммит 935672ee36
23 изменённых файлов: 445 добавлений и 30 удалений

Просмотреть файл

@ -488,13 +488,17 @@ function getFrameInfo (node, options) {
gFrameData.set(node, data);
}
// If no options specified, we can't calculate relative values, abort here
if (!options) {
return data;
}
// If a root specified, calculate the relative costs in the context of
// this call tree. The cached store may already have this, but generate
// if it does not.
let totalSamples = options.root.samples;
let totalDuration = options.root.duration;
if (options && options.root && !data.COSTS_CALCULATED) {
let totalSamples = options.root.samples;
let totalDuration = options.root.duration;
data.selfDuration = node.youngestFrameSamples / totalSamples * totalDuration;
data.selfPercentage = node.youngestFrameSamples / totalSamples * 100;
data.totalDuration = node.samples / totalSamples * totalDuration;
@ -503,8 +507,15 @@ function getFrameInfo (node, options) {
}
if (options && options.allocations && !data.ALLOCATION_DATA_CALCULATED) {
let totalBytes = options.root.byteSize;
data.selfCount = node.youngestFrameSamples;
data.totalCount = node.samples;
data.selfCountPercentage = node.youngestFrameSamples / totalSamples * 100;
data.totalCountPercentage = node.samples / totalSamples * 100;
data.selfSize = node.youngestFrameByteSize;
data.totalSize = node.byteSize;
data.selfSizePercentage = node.youngestFrameByteSize / totalBytes * 100;
data.totalSizePercentage = node.byteSize / totalBytes * 100;
data.ALLOCATION_DATA_CALCULATED = true;
}

Просмотреть файл

@ -36,6 +36,9 @@ function ThreadNode(thread, options = {}) {
this.calls = [];
this.duration = options.endTime - options.startTime;
this.nodeType = "Thread";
// Total bytesize of all allocations if enabled
this.byteSize = 0;
this.youngestFrameByteSize = 0;
let { samples, stackTable, frameTable, stringTable } = thread;
@ -108,6 +111,7 @@ ThreadNode.prototype = {
const SAMPLE_STACK_SLOT = samples.schema.stack;
const SAMPLE_TIME_SLOT = samples.schema.time;
const SAMPLE_BYTESIZE_SLOT = samples.schema.size;
const STACK_PREFIX_SLOT = stackTable.schema.prefix;
const STACK_FRAME_SLOT = stackTable.schema.frame;
@ -134,10 +138,15 @@ ThreadNode.prototype = {
isMetaCategoryOut: false
};
let byteSize = 0;
for (let i = 0; i < samplesData.length; i++) {
let sample = samplesData[i];
let sampleTime = sample[SAMPLE_TIME_SLOT];
if (SAMPLE_BYTESIZE_SLOT !== void 0) {
byteSize = sample[SAMPLE_BYTESIZE_SLOT];
}
// A sample's end time is considered to be its time of sampling. Its
// start time is the sampling time of the previous sample.
//
@ -227,11 +236,18 @@ ThreadNode.prototype = {
frameNode._addOptimizations(inflatedFrame.optimizations, inflatedFrame.implementation,
sampleTime, stringTable);
}
if (byteSize) {
frameNode.youngestFrameByteSize += byteSize;
}
}
// Don't overcount flattened recursive frames.
if (!shouldFlatten) {
frameNode.samples++;
if (byteSize) {
frameNode.byteSize += byteSize;
}
}
prevFrameKey = frameKey;
@ -241,6 +257,9 @@ ThreadNode.prototype = {
this.samples++;
this.sampleTimes.push(sampleTime);
if (byteSize) {
this.byteSize += byteSize;
}
}
},
@ -248,18 +267,18 @@ ThreadNode.prototype = {
* Uninverts the call tree after its having been built.
*/
_uninvert: function uninvert() {
function mergeOrAddFrameNode(calls, node, samples) {
function mergeOrAddFrameNode(calls, node, samples, size) {
// Unlike the inverted call tree, we don't use a root table for the top
// level, as in general, there are many fewer entry points than
// leaves. Instead, linear search is used regardless of level.
for (let i = 0; i < calls.length; i++) {
if (calls[i].key === node.key) {
let foundNode = calls[i];
foundNode._merge(node, samples);
foundNode._merge(node, samples, size);
return foundNode.calls;
}
}
let copy = node._clone(samples);
let copy = node._clone(samples, size);
calls.push(copy);
return copy.calls;
}
@ -278,11 +297,13 @@ ThreadNode.prototype = {
let node = entry.node;
let calls = node.calls;
let callSamples = 0;
let callByteSize = 0;
// Continue the depth-first walk.
for (let i = 0; i < calls.length; i++) {
workstack.push({ node: calls[i], level: entry.level + 1 });
callSamples += calls[i].samples;
callByteSize += calls[i].byteSize;
}
// The sample delta is used to distinguish stacks.
@ -307,12 +328,13 @@ ThreadNode.prototype = {
// Note that bottoming out is a degenerate where callSamples = 0.
let samplesDelta = node.samples - callSamples;
let byteSizeDelta = node.byteSize - callByteSize;
if (samplesDelta > 0) {
// Reverse the spine and add them to the uninverted call tree.
let uninvertedCalls = rootCalls;
for (let level = entry.level; level > 0; level--) {
let callee = spine[level];
uninvertedCalls = mergeOrAddFrameNode(uninvertedCalls, callee.node, samplesDelta);
uninvertedCalls = mergeOrAddFrameNode(uninvertedCalls, callee.node, samplesDelta, byteSizeDelta);
}
}
}
@ -393,6 +415,8 @@ function FrameNode(frameKey, { location, line, category, isContent }, isMetaCate
this.isMetaCategory = !!isMetaCategory;
this.category = category;
this.nodeType = "Frame";
this.byteSize = 0;
this.youngestFrameByteSize = 0;
}
FrameNode.prototype = {
@ -429,22 +453,27 @@ FrameNode.prototype = {
}
},
_clone: function (samples) {
_clone: function (samples, size) {
let newNode = new FrameNode(this.key, this, this.isMetaCategory);
newNode._merge(this, samples);
newNode._merge(this, samples, size);
return newNode;
},
_merge: function (otherNode, samples) {
_merge: function (otherNode, samples, size) {
if (this === otherNode) {
return;
}
this.samples += samples;
this.byteSize += size;
if (otherNode.youngestFrameSamples > 0) {
this.youngestFrameSamples += samples;
}
if (otherNode.youngestFrameByteSize > 0) {
this.youngestFrameByteSize += otherNode.youngestFrameByteSize;
}
if (otherNode._optimizations) {
let opts = this._optimizations;
if (opts === null) {

Просмотреть файл

@ -12,7 +12,6 @@ support-files =
# that need to be moved over to performance tool
[browser_aaa-run-first-leaktest.js]
[browser_perf-allocations-to-samples.js]
[browser_perf-categories-js-calltree.js]
[browser_perf-clear-01.js]
[browser_perf-clear-02.js]

Просмотреть файл

@ -12,7 +12,7 @@ function* spawnTest() {
Services.prefs.setBoolPref(ALLOCATIONS_PREF, true);
yield startRecording(panel);
yield waitUntil(() => PerformanceController.getCurrentRecording().getAllocations().timestamps.length);
yield waitUntil(() => PerformanceController.getCurrentRecording().getAllocations().sizes.length);
yield stopRecording(panel);
let rendered = once(MemoryCallTreeView, EVENTS.MEMORY_CALL_TREE_RENDERED);

Просмотреть файл

@ -55,6 +55,7 @@ function *testMockMemory () {
isEmptyArray(allocations.sites, "allocations.sites");
isEmptyArray(allocations.timestamps, "allocations.timestamps");
isEmptyArray(allocations.frames, "allocations.frames");
isEmptyArray(allocations.sizes, "allocations.sizes");
is(isVisible($("#overview-pane")), true,
"overview pane not hidden when server not supporting memory actors, yet UI prefs request them.");
@ -110,6 +111,7 @@ function *testMockMemoryAndTimeline() {
isEmptyArray(allocations.sites, "allocations.sites");
isEmptyArray(allocations.timestamps, "allocations.timestamps");
isEmptyArray(allocations.frames, "allocations.frames");
isEmptyArray(allocations.sizes, "allocations.sizes");
is(isVisible($("#overview-pane")), false,
"overview pane hidden when server not supporting memory/timeline actors, yet UI prefs request them.");

Просмотреть файл

@ -41,6 +41,7 @@ let test = Task.async(function*() {
isEmptyArray(allocations.sites, "allocations.sites");
isEmptyArray(allocations.timestamps, "allocations.timestamps");
isEmptyArray(allocations.frames, "allocations.frames");
isEmptyArray(allocations.sizes, "allocations.sizes");
let sampleCount = 0;

Просмотреть файл

@ -38,6 +38,7 @@ let test = Task.async(function*() {
isEmptyArray(allocations.sites, "allocations.sites");
isEmptyArray(allocations.timestamps, "allocations.timestamps");
isEmptyArray(allocations.frames, "allocations.frames");
isEmptyArray(allocations.sizes, "allocations.sizes");
let sampleCount = 0;

Просмотреть файл

@ -128,7 +128,7 @@ let test = Task.async(function*() {
memory: [].toSource(),
ticks: TICKS_DATA.toSource(),
profile: RecordingUtils.deflateProfile(JSON.parse(JSON.stringify(PROFILER_DATA))).toSource(),
allocations: ({sites:[], timestamps:[], frames:[]}).toSource(),
allocations: ({sites:[], timestamps:[], frames:[], sizes: []}).toSource(),
withTicks: true,
withMemory: false,
sampleFrequency: void 0

Просмотреть файл

@ -2,21 +2,25 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if allocations data received from the memory actor is properly
* Tests if allocations data received from the performance actor is properly
* converted to something that follows the same structure as the samples data
* received from the profiler.
*/
function test() {
let output = RecordingUtils.getProfileThreadFromAllocations(TEST_DATA);
is(output.toSource(), EXPECTED_OUTPUT.toSource(), "The output is correct.");
finish();
function run_test() {
run_next_test();
}
add_task(function () {
const { getProfileThreadFromAllocations } = require("devtools/toolkit/performance/utils");
let output = getProfileThreadFromAllocations(TEST_DATA);
equal(output.toSource(), EXPECTED_OUTPUT.toSource(), "The output is correct.");
});
let TEST_DATA = {
sites: [0, 0, 1, 2, 3],
timestamps: [50, 100, 150, 200, 250],
sizes: [0, 0, 100, 200, 300],
frames: [
null, {
source: "A",
@ -46,11 +50,12 @@ let EXPECTED_OUTPUT = {
"schema": {
"stack": 0,
"time": 1,
"size": 2,
},
data: [
[ 1, 150 ],
[ 2, 200 ],
[ 3, 250 ]
[ 1, 150, 100 ],
[ 2, 200, 200 ],
[ 3, 250, 300 ]
]
},
stackTable: {

Просмотреть файл

@ -0,0 +1,93 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the tree model calculates correct costs/percentages for
* allocation frame nodes.
*/
function run_test() {
run_next_test();
}
add_task(function () {
let { ThreadNode } = require("devtools/performance/tree-model");
const { getProfileThreadFromAllocations } = require("devtools/toolkit/performance/utils");
let allocationData = getProfileThreadFromAllocations(TEST_DATA);
let thread = new ThreadNode(allocationData, { startTime: 0, endTime: 1000 });
/**
* Values are in order according to:
* +-------------+------------+-------------+-------------+------------------------------+
* | Self Bytes | Self Count | Total Bytes | Total Count | Function |
* +-------------+------------+-------------+-------------+------------------------------+
* | 1790272 41% | 8307 17% | 1790372 42% | 8317 18% | V someFunc @ a.j:345:6 |
* | 100 1% | 10 1% | 100 1% | 10 1% | > callerFunc @ b.j:765:34 |
* +-------------+------------+-------------+-------------+------------------------------+
*/
[
[100, 10, 1, 33, 1000, 100, 3, 100, "x (A:1:2)", [
[200, 20, 1, 33, 900, 90, 2, 66, "y (B:3:4)", [
[700, 70, 1, 33, 700, 70, 1, 33, "z (C:5:6)"]
]]
]]
].forEach(compareFrameInfo(thread));
});
function compareFrameInfo (root, parent) {
parent = parent || root;
let fields = [
"selfSize", "selfSizePercentage", "selfCount", "selfCountPercentage",
"totalSize", "totalSizePercentage", "totalCount", "totalCountPercentage"
];
return function (def) {
let children;
if (Array.isArray(def[def.length - 1])) {
children = def.pop();
}
let name = def.pop();
let expected = def;
let node = getFrameNodePath(parent, name);
let data = node.getInfo({ root, allocations: true });
fields.forEach((field, i) => {
let actual = data[field];
if (/percentage/i.test(field)) {
actual = Number.parseInt(actual, 10);
}
equal(actual, expected[i], `${name} has correct ${field}: ${expected[i]}`);
});
if (children) {
children.forEach(compareFrameInfo(root, node));
}
}
}
let TEST_DATA = {
sites: [1, 2, 3],
timestamps: [150, 200, 250],
sizes: [100, 200, 700],
frames: [
null, {
source: "A",
line: 1,
column: 2,
functionDisplayName: "x",
parent: 0
}, {
source: "B",
line: 3,
column: 4,
functionDisplayName: "y",
parent: 1
}, {
source: "C",
line: 5,
column: 6,
functionDisplayName: "z",
parent: 2
}
]
};

Просмотреть файл

@ -0,0 +1,101 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the tree model calculates correct costs/percentages for
* allocation frame nodes. Inverted version of test_tree-model-allocations-01.js
*/
function run_test() {
run_next_test();
}
add_task(function () {
let { ThreadNode } = require("devtools/performance/tree-model");
const { getProfileThreadFromAllocations } = require("devtools/toolkit/performance/utils");
let allocationData = getProfileThreadFromAllocations(TEST_DATA);
let thread = new ThreadNode(allocationData, { invertTree: true, startTime: 0, endTime: 1000 });
/**
* Values are in order according to:
* +-------------+------------+-------------+-------------+------------------------------+
* | Self Bytes | Self Count | Total Bytes | Total Count | Function |
* +-------------+------------+-------------+-------------+------------------------------+
* | 1790272 41% | 8307 17% | 1790372 42% | 8317 18% | V someFunc @ a.j:345:6 |
* | 100 1% | 10 1% | 100 1% | 10 1% | > callerFunc @ b.j:765:34 |
* +-------------+------------+-------------+-------------+------------------------------+
*/
[
[700, 70, 1, 33, 700, 70, 1, 33, "z (C:5:6)", [
[0, 0, 0, 0, 700, 70, 1, 33, "y (B:3:4)", [
[0, 0, 0, 0, 700, 70, 1, 33, "x (A:1:2)"]
]]
]],
[200, 20, 1, 33, 200, 20, 1, 33, "y (B:3:4)", [
[0, 0, 0, 0, 200, 20, 1, 33, "x (A:1:2)"]
]],
[100, 10, 1, 33, 100, 10, 1, 33, "x (A:1:2)"]
].forEach(compareFrameInfo(thread));
});
function compareFrameInfo (root, parent) {
parent = parent || root;
let fields = [
"selfSize", "selfSizePercentage", "selfCount", "selfCountPercentage",
"totalSize", "totalSizePercentage", "totalCount", "totalCountPercentage"
];
return function (def) {
let children;
if (Array.isArray(def[def.length - 1])) {
children = def.pop();
}
let name = def.pop();
let expected = def;
let node = getFrameNodePath(parent, name);
let data = node.getInfo({ root, allocations: true });
fields.forEach((field, i) => {
let actual = data[field];
if (/percentage/i.test(field)) {
actual = Number.parseInt(actual, 10);
}
equal(actual, expected[i], `${name} has correct ${field}: ${expected[i]}`);
});
if (children) {
children.forEach(compareFrameInfo(root, node));
}
}
}
let TEST_DATA = {
sites: [0, 1, 2, 3],
timestamps: [0, 150, 200, 250],
sizes: [0, 100, 200, 700],
frames: [{
source: "(root)"
}, {
source: "A",
line: 1,
column: 2,
functionDisplayName: "x",
parent: 0
}, {
source: "B",
line: 3,
column: 4,
functionDisplayName: "y",
parent: 1
}, {
source: "C",
line: 5,
column: 6,
functionDisplayName: "z",
parent: 2
}
]
};

Просмотреть файл

@ -13,6 +13,7 @@ skip-if = toolkit == 'android' || toolkit == 'gonk'
[test_jit-graph-data.js]
[test_jit-model-01.js]
[test_jit-model-02.js]
[test_perf-utils-allocations-to-samples.js]
[test_tree-model-01.js]
[test_tree-model-02.js]
[test_tree-model-03.js]
@ -26,6 +27,8 @@ skip-if = toolkit == 'android' || toolkit == 'gonk'
[test_tree-model-11.js]
[test_tree-model-12.js]
[test_tree-model-13.js]
[test_tree-model-allocations-01.js]
[test_tree-model-allocations-02.js]
[test_waterfall-utils-collapse-01.js]
[test_waterfall-utils-collapse-02.js]
[test_waterfall-utils-collapse-03.js]

Просмотреть файл

@ -144,7 +144,7 @@ function convertLegacyData (legacyData) {
frames: [],
memory: [],
ticks: ticksData,
allocations: { sites: [], timestamps: [], frames: [] },
allocations: { sites: [], timestamps: [], frames: [], sizes: [] },
profile: profilerData.profile,
// Fake a configuration object here if there's tick data,
// so that it can be rendered

Просмотреть файл

@ -116,7 +116,7 @@ LegacyPerformanceRecording.prototype = {
this._frames = [];
this._memory = [];
this._ticks = [];
this._allocations = { sites: [], timestamps: [], frames: [] };
this._allocations = { sites: [], timestamps: [], frames: [], sizes: [] };
},
/**

Просмотреть файл

@ -4,6 +4,8 @@
# 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/.
XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
EXTRA_JS_MODULES.devtools.performance += [
'io.js',
'process-communication.js',

Просмотреть файл

@ -0,0 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
let { require } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {});

Просмотреть файл

@ -0,0 +1,93 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if allocations data received from the performance actor is properly
* converted to something that follows the same structure as the samples data
* received from the profiler.
*/
function run_test() {
run_next_test();
}
add_task(function () {
const { getProfileThreadFromAllocations } = require("devtools/toolkit/performance/utils");
let output = getProfileThreadFromAllocations(TEST_DATA);
equal(output.toSource(), EXPECTED_OUTPUT.toSource(), "The output is correct.");
});
let TEST_DATA = {
sites: [0, 0, 1, 2, 3],
timestamps: [50, 100, 150, 200, 250],
sizes: [0, 0, 100, 200, 300],
frames: [
null, {
source: "A",
line: 1,
column: 2,
functionDisplayName: "x",
parent: 0
}, {
source: "B",
line: 3,
column: 4,
functionDisplayName: "y",
parent: 1
}, {
source: "C",
line: 5,
column: 6,
functionDisplayName: null,
parent: 2
}
]
};
let EXPECTED_OUTPUT = {
name: "allocations",
samples: {
"schema": {
"stack": 0,
"time": 1,
"size": 2,
},
data: [
[ 1, 150, 100 ],
[ 2, 200, 200 ],
[ 3, 250, 300 ]
]
},
stackTable: {
"schema": {
"prefix": 0,
"frame": 1
},
"data": [
null,
[ null, 1 ], // x (A:1:2)
[ 1, 2 ], // x (A:1:2) > y (B:3:4)
[ 2, 3 ] // x (A:1:2) > y (B:3:4) > C:5:6
]
},
frameTable: {
"schema": {
"location": 0,
"implementation": 1,
"optimizations": 2,
"line": 3,
"category": 4
},
data: [
null,
[ 0 ],
[ 1 ],
[ 2 ]
]
},
"stringTable": [
"x (A:1:2)",
"y (B:3:4)",
"C:5:6"
],
};

Просмотреть файл

@ -0,0 +1,7 @@
[DEFAULT]
tags = devtools
head = head.js
tail =
skip-if = toolkit == 'android' || toolkit == 'gonk'
[test_perf-utils-allocations-to-samples.js]

Просмотреть файл

@ -157,7 +157,7 @@ let gProfileThreadFromAllocationCache = new WeakMap();
* @see MemoryActor.prototype.getAllocations for more information.
*
* @param object allocations
* A list of { sites, timestamps, frames, counts } arrays.
* A list of { sites, timestamps, frames, sizes } arrays.
* @return object
* The "profile" describing the allocations log.
*/
@ -167,7 +167,7 @@ function getProfileThreadFromAllocations(allocations) {
return cached;
}
let { sites, timestamps, frames } = allocations;
let { sites, timestamps, frames, sizes } = allocations;
let uniqueStrings = new UniqueStrings();
// Convert allocation frames to the the stack and frame tables expected by
@ -239,14 +239,14 @@ function getProfileThreadFromAllocations(allocations) {
let writePos = 0;
for (let i = 0; i < sites.length; i++) {
// Schema:
// [stack, time]
// [stack, time, size]
//
// Originally, sites[i] indexes into the frames array. Note that in the
// loop above, stackTable[sites[i]] and frames[sites[i]] index the same
// information.
let stackIndex = sites[i];
if (frames[stackIndex]) {
samples[writePos++] = [stackIndex, timestamps[i]];
samples[writePos++] = [stackIndex, timestamps[i], sizes[i]];
}
}
samples.length = writePos;
@ -269,6 +269,7 @@ function allocationsWithSchema (data) {
schema: {
stack: slot++,
time: slot++,
size: slot++,
},
data: data
};

Просмотреть файл

@ -163,7 +163,7 @@ let PerformanceRecordingActor = exports.PerformanceRecordingActor = protocol.Act
this._frames = [];
this._memory = [];
this._ticks = [];
this._allocations = { sites: [], timestamps: [], frames: [], counts: [] };
this._allocations = { sites: [], timestamps: [], frames: [], sizes: [] };
}
},
@ -252,7 +252,7 @@ let PerformanceRecordingFront = exports.PerformanceRecordingFront = protocol.Fro
this._frames = [];
this._memory = [];
this._ticks = [];
this._allocations = { sites: [], timestamps: [], frames: [], counts: [] };
this._allocations = { sites: [], timestamps: [], frames: [], sizes: [] };
},
destroy: function () {
@ -344,6 +344,7 @@ let PerformanceRecordingFront = exports.PerformanceRecordingFront = protocol.Fro
let {
allocations: sites,
allocationsTimestamps: timestamps,
allocationSizes: sizes,
frames,
} = data;
@ -351,6 +352,7 @@ let PerformanceRecordingFront = exports.PerformanceRecordingFront = protocol.Fro
RecordingUtils.pushAll(this._allocations.sites, sites);
RecordingUtils.pushAll(this._allocations.timestamps, timestamps);
RecordingUtils.pushAll(this._allocations.frames, frames);
RecordingUtils.pushAll(this._allocations.sizes, sizes);
break;
}
}

Просмотреть файл

@ -4,6 +4,7 @@ subsuite = devtools
support-files =
head.js
animation.html
doc_allocations.html
doc_force_cc.html
doc_force_gc.html
doc_innerHTML.html
@ -56,6 +57,8 @@ skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are
[browser_markers-timestamp.js]
[browser_navigateEvents.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_perf-allocation-data.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_perf-legacy-front-01.js]
skip-if = e10s # Bug 1183605 - toolkit/devtools/server/tests/browser/ tests are still disabled in E10S
[browser_perf-legacy-front-02.js]

Просмотреть файл

@ -0,0 +1,36 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test that we have allocation data coming from the front.
*/
const { PerformanceFront } = require("devtools/server/actors/performance");
add_task(function*() {
let doc = yield addTab(MAIN_DOMAIN + "doc_allocations.html");
initDebuggerServer();
let client = new DebuggerClient(DebuggerServer.connectPipe());
let form = yield connectDebuggerClient(client);
let front = PerformanceFront(client, form);
yield front.connect();
let rec = yield front.startRecording({ withMarkers: true, withAllocations: true, withTicks: true });
yield waitUntil(() => rec.getAllocations().frames.length);
yield waitUntil(() => rec.getAllocations().timestamps.length);
yield waitUntil(() => rec.getAllocations().sizes.length);
yield waitUntil(() => rec.getAllocations().sites.length);
yield front.stopRecording(rec);
let { frames, timestamps, sizes, sites } = rec.getAllocations();
is(timestamps.length, sizes.length, "we have the same amount of timestamps and sizes");
ok(timestamps.every(time => time > 0 && typeof time === "number"), "all timestamps have numeric values");
ok(sizes.every(n => n > 0 && typeof n === "number"), "all sizes are positive numbers");
yield closeDebuggerClient(client);
gBrowser.removeCurrentTab();
});

Просмотреть файл

@ -0,0 +1,19 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script>
window.onload = function() {
var allocs = [];
function allocator() {
allocs.push(new Object);
}
window.setInterval(allocator, 1);
};
</script>
</pre>
</body>
</html>