Bug 1129187 - Initialize all the overview graphs and detail views lazily, r=jsantell

This commit is contained in:
Victor Porof 2015-02-06 13:20:19 -05:00
Родитель ba559120ac
Коммит 95ac757463
42 изменённых файлов: 451 добавлений и 185 удалений

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

@ -60,9 +60,8 @@ const EVENTS = {
// Fired by the OptionsView when a preference changes.
PREF_CHANGED: "Performance:PrefChanged",
// Emitted by the PerformanceController or RecordingView
// when a recording model is selected
RECORDING_SELECTED: "Performance:RecordingSelected",
// Emitted by the PerformanceView when the state (display mode) changes.
UI_STATE_CHANGED: "Performance:UI:StateChanged",
// Emitted by the PerformanceView on clear button click
UI_CLEAR_RECORDINGS: "Performance:UI:ClearRecordings",
@ -82,6 +81,10 @@ const EVENTS = {
RECORDING_WILL_START: "Performance:RecordingWillStart",
RECORDING_WILL_STOP: "Performance:RecordingWillStop",
// Emitted by the PerformanceController or RecordingView
// when a recording model is selected
RECORDING_SELECTED: "Performance:RecordingSelected",
// When recordings have been cleared out
RECORDINGS_CLEARED: "Performance:RecordingsCleared",
@ -241,7 +244,6 @@ let PerformanceController = {
let recording = this._getLatestRecording();
this.emit(EVENTS.RECORDING_WILL_STOP, recording);
yield recording.stopRecording();
this.emit(EVENTS.RECORDING_STOPPED, recording);
}),

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

@ -29,7 +29,7 @@ let PerformanceView = {
/**
* Sets up the view with event binding and main subviews.
*/
initialize: function () {
initialize: Task.async(function* () {
this._recordButton = $("#main-record-button");
this._importButton = $("#import-button");
this._clearButton = $("#clear-button");
@ -59,18 +59,18 @@ let PerformanceView = {
this.setState("empty");
return promise.all([
RecordingsView.initialize(),
OverviewView.initialize(),
ToolbarView.initialize(),
DetailsView.initialize()
]);
},
// Initialize the ToolbarView first, because other views may need access
// to the OptionsView via the controller, to read prefs.
yield ToolbarView.initialize();
yield RecordingsView.initialize();
yield OverviewView.initialize();
yield DetailsView.initialize();
}),
/**
* Unbinds events and destroys subviews.
*/
destroy: function () {
destroy: Task.async(function* () {
for (let button of $$(".record-button")) {
button.removeEventListener("click", this._onRecordButtonClick);
}
@ -82,13 +82,11 @@ let PerformanceView = {
PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
PerformanceController.off(EVENTS.RECORDING_SELECTED, this._onRecordingSelected);
return promise.all([
RecordingsView.destroy(),
OverviewView.destroy(),
ToolbarView.destroy(),
DetailsView.destroy()
]);
},
yield ToolbarView.destroy();
yield RecordingsView.destroy();
yield OverviewView.destroy();
yield DetailsView.destroy();
}),
/**
* Sets the state of the profiler view. Possible options are "empty",
@ -104,6 +102,7 @@ let PerformanceView = {
}
this._state = state;
this.emit(EVENTS.UI_STATE_CHANGED, state);
},
/**

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

@ -55,6 +55,7 @@ support-files =
[browser_perf-overview-time-interval.js]
[browser_perf-shared-connection-02.js]
[browser_perf-shared-connection-03.js]
[browser_perf-states.js]
[browser_perf-ui-recording.js]
[browser_perf-recording-notices-01.js]
[browser_perf-recording-notices-02.js]

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

@ -20,22 +20,19 @@ let TEST_DATA = {
sites: [0, 0, 1, 2, 3],
timestamps: [50, 100, 150, 200, 250],
frames: [
null,
{
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,

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

@ -8,7 +8,7 @@
let test = Task.async(function*() {
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
let { EVENTS, PerformanceController, PerformanceView, RecordingsView } = panel.panelWin;
let { EVENTS, PerformanceController, PerformanceView, RecordingsView, OverviewView } = panel.panelWin;
yield startRecording(panel);
yield stopRecording(panel);

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

@ -14,7 +14,7 @@ function spawnTest () {
let selected = DetailsView.whenViewSelected(JsCallTreeView);
let notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED);
DetailsView.selectView("js-calltree");
yield DetailsView.selectView("js-calltree");
yield Promise.all([selected, notified]);
ok(DetailsView.isViewSelected(JsCallTreeView),
@ -22,7 +22,7 @@ function spawnTest () {
selected = DetailsView.whenViewSelected(JsFlameGraphView);
notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED);
DetailsView.selectView("js-flamegraph");
yield DetailsView.selectView("js-flamegraph");
yield Promise.all([selected, notified]);
ok(DetailsView.isViewSelected(JsFlameGraphView),
@ -30,7 +30,7 @@ function spawnTest () {
selected = DetailsView.whenViewSelected(WaterfallView);
notified = DetailsView.once(EVENTS.DETAILS_VIEW_SELECTED);
DetailsView.selectView("waterfall");
yield DetailsView.selectView("waterfall");
yield Promise.all([selected, notified]);
ok(DetailsView.isViewSelected(WaterfallView),

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

@ -40,6 +40,7 @@ function spawnTest () {
ok(DetailsView.isViewSelected(WaterfallView),
"The waterfall view is now selected when toggling off enable-memory when a memory panel is selected.");
Services.prefs.setBoolPref(MEMORY_PREF, true);
selected = DetailsView.whenViewSelected(MemoryFlameGraphView);

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

@ -8,7 +8,7 @@ function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
DetailsView.selectView("js-calltree");
yield DetailsView.selectView("js-calltree");
ok(DetailsView.isViewSelected(JsCallTreeView), "The call tree is now selected.");
yield startRecording(panel);

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

@ -8,7 +8,7 @@ function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
DetailsView.selectView("js-flamegraph");
yield DetailsView.selectView("js-flamegraph");
ok(DetailsView.isViewSelected(JsFlameGraphView), "The flamegraph is now selected.");
yield startRecording(panel);

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

@ -8,7 +8,7 @@ function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, DetailsView, MemoryCallTreeView } = panel.panelWin;
DetailsView.selectView("memory-calltree");
yield DetailsView.selectView("memory-calltree");
ok(DetailsView.isViewSelected(MemoryCallTreeView), "The call tree is now selected.");
yield startRecording(panel);

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

@ -8,7 +8,7 @@ function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, DetailsView, MemoryFlameGraphView } = panel.panelWin;
DetailsView.selectView("memory-flamegraph");
yield DetailsView.selectView("memory-flamegraph");
ok(DetailsView.isViewSelected(MemoryFlameGraphView), "The flamegraph is now selected.");
yield startRecording(panel);

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

@ -10,16 +10,36 @@ let WAIT_TIME = 1000;
function spawnTest () {
let { target, front } = yield initBackend(SIMPLE_URL);
let { profilerStartTime, timelineStartTime } = yield front.startRecording();
let startData = yield front.startRecording();
let { profilerStartTime, timelineStartTime, memoryStartTime } = startData;
ok("profilerStartTime" in startData,
"A `profilerStartTime` property is properly set in the recording data.");
ok("timelineStartTime" in startData,
"A `timelineStartTime` property is properly set in the recording data.");
ok("memoryStartTime" in startData,
"A `memoryStartTime` property is properly set in the recording data.");
ok(profilerStartTime !== undefined,
"A `profilerStartTime` property exists in the recording data.");
ok(timelineStartTime !== undefined,
"A `timelineStartTime` property exists in the recording data.");
is(memoryStartTime, 0,
"A `memoryStartTime` property exists in the recording data, but it's 0.");
yield busyWait(WAIT_TIME);
let { profile, profilerEndTime, timelineEndTime } = yield front.stopRecording();
let stopData = yield front.stopRecording();
let { profile, profilerEndTime, timelineEndTime, memoryEndTime } = stopData;
ok("profile" in stopData,
"A `profile` property is properly set in the recording data.");
ok("profilerEndTime" in stopData,
"A `profilerEndTime` property is properly set in the recording data.");
ok("timelineEndTime" in stopData,
"A `timelineEndTime` property is properly set in the recording data.");
ok("memoryEndTime" in stopData,
"A `memoryEndTime` property is properly set in the recording data.");
ok(profile,
"A `profile` property exists in the recording data.");
@ -27,6 +47,8 @@ function spawnTest () {
"A `profilerEndTime` property exists in the recording data.");
ok(timelineEndTime !== undefined,
"A `timelineEndTime` property exists in the recording data.");
is(memoryEndTime, 0,
"A `memoryEndTime` property exists in the recording data, but it's 0.");
yield removeTab(target.tab);
finish();

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

@ -28,9 +28,7 @@ function spawnTest () {
front.on("ticks", handler);
yield front.startRecording({ withMemory: true, withTicks: true });
yield Promise.all(Object.keys(deferreds).map(type => deferreds[type].promise));
yield front.stopRecording();
is(counters.markers.length, 1, "one marker event fired.");

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

@ -31,7 +31,9 @@ function spawnTest () {
profilerEndTime,
timelineEndTime,
memoryEndTime
} = yield front.stopRecording();
} = yield front.stopRecording({
withAllocations: true
});
ok(typeof profilerEndTime === "number",
"The front.stopRecording() emits a profiler end time.");

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

@ -2,8 +2,8 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests if the performance tool can jump to the debugger, when the source was already
* loaded in that tool.
* Tests if the performance tool can jump to the debugger, when the source was
* already loaded in that tool.
*/
function spawnTest() {

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

@ -8,7 +8,7 @@ function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
DetailsView.selectView("js-calltree");
yield DetailsView.selectView("js-calltree");
// Manually call the _onPrefChanged function so we can catch an error
try {

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

@ -8,7 +8,7 @@ function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
DetailsView.selectView("js-calltree");
yield DetailsView.selectView("js-calltree");
yield startRecording(panel);

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

@ -25,6 +25,7 @@ function spawnTest () {
yield startRecording(panel);
Services.prefs.setBoolPref(MEMORY_PREF, false);
yield stopRecording(panel);
is(PerformanceController.getCurrentRecording().getConfiguration().withMemory, true,
"The recording finished with tracking memory.");
is(PerformanceController.getCurrentRecording().getConfiguration().withAllocations, true,

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

@ -2,16 +2,16 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the js Flamegraphs gets rerendered when toggling `flatten-tree-recursion`
* Tests that the js flamegraphs get rerendered when toggling `flatten-tree-recursion`
*/
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
DetailsView.selectView("js-flamegraph");
Services.prefs.setBoolPref(FLATTEN_PREF, true);
yield DetailsView.selectView("js-flamegraph");
yield startRecording(panel);
yield busyWait(100);

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

@ -2,19 +2,18 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the memory Flamegraphs gets rerendered when toggling `flatten-tree-recursion`
* Tests that the memory flamegraphs get rerendered when toggling `flatten-tree-recursion`
*/
function spawnTest () {
// Enable memory to test
Services.prefs.setBoolPref(MEMORY_PREF, true);
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, DetailsView, MemoryFlameGraphView } = panel.panelWin;
DetailsView.selectView("memory-flamegraph");
// Enable memory to test
Services.prefs.setBoolPref(MEMORY_PREF, true);
Services.prefs.setBoolPref(FLATTEN_PREF, true);
yield DetailsView.selectView("memory-flamegraph");
yield startRecording(panel);
yield busyWait(100);

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

@ -2,8 +2,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the js call tree view is re-rendered after the
* "invert-call-tree" pref is changed.
* Tests that the js call tree views get rerendered when toggling `invert-call-tree`
*/
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
@ -11,7 +10,7 @@ function spawnTest () {
Services.prefs.setBoolPref(INVERT_PREF, true);
DetailsView.selectView("js-calltree");
yield DetailsView.selectView("js-calltree");
ok(DetailsView.isViewSelected(JsCallTreeView), "The call tree is now selected.");
yield startRecording(panel);

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

@ -2,8 +2,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the memory call tree view is re-rendered after the
* "invert-call-tree" pref is changed.
* Tests that the memory call tree views get rerendered when toggling `invert-call-tree`
*/
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
@ -13,7 +12,7 @@ function spawnTest () {
Services.prefs.setBoolPref(MEMORY_PREF, true);
Services.prefs.setBoolPref(INVERT_PREF, true);
DetailsView.selectView("memory-calltree");
yield DetailsView.selectView("memory-calltree");
ok(DetailsView.isViewSelected(MemoryCallTreeView), "The call tree is now selected.");
yield startRecording(panel);

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

@ -2,16 +2,16 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the js Flamegraphs gets rerendered when toggling `show-idle-blocks`
* Tests that the js flamegraphs get rerendered when toggling `show-idle-blocks`
*/
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
DetailsView.selectView("js-flamegraph");
Services.prefs.setBoolPref(IDLE_PREF, true);
yield DetailsView.selectView("js-flamegraph");
yield startRecording(panel);
yield busyWait(100);

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

@ -2,7 +2,7 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the memory Flamegraphs gets rerendered when toggling `show-idle-blocks`
* Tests that the memory flamegraphs get rerendered when toggling `show-idle-blocks`
*/
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
@ -10,10 +10,10 @@ function spawnTest () {
// Enable memory to test
Services.prefs.setBoolPref(MEMORY_PREF, true);
DetailsView.selectView("memory-flamegraph");
Services.prefs.setBoolPref(IDLE_PREF, true);
yield DetailsView.selectView("memory-flamegraph");
yield startRecording(panel);
yield busyWait(100);

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

@ -2,16 +2,16 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the JsCallTree get rerendered when toggling `show-platform-data`
* Tests that the js call tree views get rerendered when toggling `show-platform-data`
*/
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, DetailsView, JsFlameGraphView, JsCallTreeView } = panel.panelWin;
DetailsView.selectView("js-calltree");
let { EVENTS, DetailsView, JsCallTreeView } = panel.panelWin;
Services.prefs.setBoolPref(PLATFORM_DATA_PREF, true);
yield DetailsView.selectView("js-calltree");
yield startRecording(panel);
yield busyWait(100);

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

@ -2,14 +2,15 @@
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that the JsFlamegraphs get rerendered when toggling `show-platform-data`
* Tests that the js flamegraphs get rerendered when toggling `show-platform-data`
*/
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, DetailsView, JsFlameGraphView } = panel.panelWin;
Services.prefs.setBoolPref(PLATFORM_DATA_PREF, false);
DetailsView.selectView("js-flamegraph");
yield DetailsView.selectView("js-flamegraph");
yield startRecording(panel);
yield busyWait(100);

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

@ -8,6 +8,9 @@ function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, OverviewView } = panel.panelWin;
// Enable memory to test all the overview graphs.
Services.prefs.setBoolPref(MEMORY_PREF, true);
yield startRecording(panel);
yield Promise.all([

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

@ -9,8 +9,18 @@ function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, OverviewView } = panel.panelWin;
// Enable memory to test all the overview graphs.
Services.prefs.setBoolPref(MEMORY_PREF, true);
yield startRecording(panel);
yield Promise.all([
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
once(OverviewView, EVENTS.MEMORY_GRAPH_RENDERED),
once(OverviewView, EVENTS.OVERVIEW_RENDERED),
]);
ok("selectionEnabled" in OverviewView.framerateGraph,
"The selection should not be enabled for the framerate overview (1).");
is(OverviewView.framerateGraph.selectionEnabled, false,

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

@ -8,8 +8,8 @@ function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, PerformanceController, OverviewView } = panel.panelWin;
Services.prefs.setBoolPref("devtools.performance.ui.enable-memory", true);
Services.prefs.setBoolPref("devtools.performance.ui.enable-framerate", true);
// Enable memory to test all the overview graphs.
Services.prefs.setBoolPref(MEMORY_PREF, true);
yield startRecording(panel);
@ -24,9 +24,6 @@ function spawnTest () {
yield stopRecording(panel);
// Wait for the overview graph to be rerendered *after* recording.
yield once(OverviewView, EVENTS.OVERVIEW_RENDERED);
ok(OverviewView.markersOverview.width > 0,
"The overview's framerate graph has a width.");
ok(OverviewView.markersOverview.dataScaleX > 0,

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

@ -11,14 +11,14 @@ function spawnTest () {
yield startRecording(panel);
// Wait for the overview graph to be rendered while recording.
yield once(OverviewView, EVENTS.OVERVIEW_RENDERED);
yield Promise.all([
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
once(OverviewView, EVENTS.OVERVIEW_RENDERED)
]);
yield stopRecording(panel);
// Wait for the overview graph to be rerendered *after* recording.
yield once(OverviewView, EVENTS.OVERVIEW_RENDERED);
let graph = OverviewView.markersOverview;
let MAX = graph.width;

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

@ -7,12 +7,30 @@
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, OverviewView } = panel.panelWin;
let framerateGraph = OverviewView.framerateGraph;
let markersOverview = OverviewView.markersOverview;
let memoryOverview = OverviewView.memoryOverview;
// Enable memory to test all the overview graphs.
Services.prefs.setBoolPref(MEMORY_PREF, true);
yield startRecording(panel);
yield Promise.all([
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
once(OverviewView, EVENTS.MEMORY_GRAPH_RENDERED),
once(OverviewView, EVENTS.OVERVIEW_RENDERED),
]);
let markersOverview = OverviewView.markersOverview;
let memoryOverview = OverviewView.memoryOverview;
let framerateGraph = OverviewView.framerateGraph;
ok(markersOverview,
"The markers graph should have been created now.");
ok(memoryOverview,
"The memory graph should have been created now.");
ok(framerateGraph,
"The framerate graph should have been created now.");
ok(!framerateGraph.selectionEnabled,
"Selection shouldn't be enabled when the first recording started (1).");
ok(!markersOverview.selectionEnabled,
@ -31,6 +49,13 @@ function spawnTest () {
yield startRecording(panel);
yield Promise.all([
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
once(OverviewView, EVENTS.MEMORY_GRAPH_RENDERED),
once(OverviewView, EVENTS.OVERVIEW_RENDERED),
]);
ok(!framerateGraph.selectionEnabled,
"Selection shouldn't be enabled when the second recording started (1).");
ok(!markersOverview.selectionEnabled,

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

@ -7,15 +7,26 @@
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, OverviewView } = panel.panelWin;
// Enable memory to test all the overview graphs.
Services.prefs.setBoolPref(MEMORY_PREF, true);
yield startRecording(panel);
yield Promise.all([
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
once(OverviewView, EVENTS.MEMORY_GRAPH_RENDERED),
once(OverviewView, EVENTS.OVERVIEW_RENDERED),
]);
yield stopRecording(panel);
let framerateGraph = OverviewView.framerateGraph;
let markersOverview = OverviewView.markersOverview;
let memoryOverview = OverviewView.memoryOverview;
let MAX = framerateGraph.width;
yield startRecording(panel);
yield stopRecording(panel);
// Perform a selection inside the framerate graph.
let selected = once(OverviewView, EVENTS.OVERVIEW_RANGE_SELECTED);

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

@ -24,11 +24,14 @@ function spawnTest () {
}
yield startRecording(panel);
busyWait(100);
let rendered = once(OverviewView, EVENTS.OVERVIEW_RENDERED);
yield Promise.all([
once(OverviewView, EVENTS.FRAMERATE_GRAPH_RENDERED),
once(OverviewView, EVENTS.MARKERS_GRAPH_RENDERED),
once(OverviewView, EVENTS.OVERVIEW_RENDERED)
]);
yield stopRecording(panel);
yield rendered;
// Get/set the time interval and wait for the event propagation.

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

@ -27,12 +27,12 @@ function spawnTest () {
ok(true, "Waterfall rerenders when a range in the overview graph is selected.");
rendered = once(JsCallTreeView, EVENTS.JS_CALL_TREE_RENDERED);
DetailsView.selectView("js-calltree");
yield DetailsView.selectView("js-calltree");
yield rendered;
ok(true, "Call tree rerenders after its corresponding pane is shown.");
rendered = once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED);
DetailsView.selectView("js-flamegraph");
yield DetailsView.selectView("js-flamegraph");
yield rendered;
ok(true, "Flamegraph rerenders after its corresponding pane is shown.");
@ -42,12 +42,12 @@ function spawnTest () {
ok(true, "Flamegraph rerenders when a range in the overview graph is removed.");
rendered = once(JsCallTreeView, EVENTS.JS_CALL_TREE_RENDERED);
DetailsView.selectView("js-calltree");
yield DetailsView.selectView("js-calltree");
yield rendered;
ok(true, "Call tree rerenders after its corresponding pane is shown.");
rendered = once(WaterfallView, EVENTS.WATERFALL_RENDERED);
DetailsView.selectView("waterfall");
yield DetailsView.selectView("waterfall");
yield rendered;
ok(true, "Waterfall rerenders after its corresponding pane is shown.");

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

@ -8,10 +8,23 @@
let test = Task.async(function*() {
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
let { $, EVENTS, PerformanceController, DetailsSubview, RecordingsView } = panel.panelWin;
let { $, EVENTS, PerformanceController, DetailsView, DetailsSubview, RecordingsView } = panel.panelWin;
// Enable memory to test the memory-calltree and memory-flamegraph.
Services.prefs.setBoolPref(MEMORY_PREF, true);
// Need to allow widgets to be updated while hidden, otherwise we can't use
// `waitForWidgetsRendered`.
DetailsSubview.canUpdateWhileHidden = true;
// Cycle through all the views to initialize them, otherwise we can't use
// `waitForWidgetsRendered`. The waterfall is shown by default, but all the
// other views are created lazily, so won't emit any events.
yield DetailsView.selectView("js-calltree");
yield DetailsView.selectView("js-flamegraph");
yield DetailsView.selectView("memory-calltree");
yield DetailsView.selectView("memory-flamegraph");
yield startRecording(panel);
yield stopRecording(panel);

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

@ -0,0 +1,95 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Tests that view states and lazy component intialization works.
*/
function spawnTest () {
let { panel } = yield initPerformance(SIMPLE_URL);
let { EVENTS, PerformanceView, OverviewView, DetailsView } = panel.panelWin;
is(PerformanceView.getState(), "empty",
"The intial state of the performance panel view is correct.");
ok(!("markersOverview" in OverviewView),
"The markers graph should not have been created yet.");
ok(!("memoryOverview" in OverviewView),
"The memory graph should not have been created yet.");
ok(!("framerateGraph" in OverviewView),
"The framerate graph should not have been created yet.");
ok(DetailsView.components["waterfall"].initialized,
"The waterfall detail view should have been created by default.");
ok(!DetailsView.components["js-calltree"].initialized,
"The js-calltree detail view should not have been created yet.");
ok(!DetailsView.components["js-flamegraph"].initialized,
"The js-flamegraph detail view should not have been created yet.");
ok(!DetailsView.components["memory-calltree"].initialized,
"The memory-calltree detail view should not have been created yet.");
ok(!DetailsView.components["memory-flamegraph"].initialized,
"The memory-flamegraph detail view should not have been created yet.");
Services.prefs.setBoolPref(MEMORY_PREF, true);
ok(!("markersOverview" in OverviewView),
"The markers graph should still not have been created yet.");
ok(!("memoryOverview" in OverviewView),
"The memory graph should still not have been created yet.");
ok(!("framerateGraph" in OverviewView),
"The framerate graph should still not have been created yet.");
let stateChanged = once(PerformanceView, EVENTS.UI_STATE_CHANGED);
yield startRecording(panel);
yield stateChanged;
is(PerformanceView.getState(), "recording",
"The current state of the performance panel view is 'recording'.");
ok(OverviewView.memoryOverview,
"The memory graph should have been created now.");
ok(OverviewView.framerateGraph,
"The framerate graph should have been created now.");
stateChanged = once(PerformanceView, EVENTS.UI_STATE_CHANGED);
yield stopRecording(panel);
yield stateChanged;
is(PerformanceView.getState(), "recorded",
"The current state of the performance panel view is 'recorded'.");
ok(!DetailsView.components["js-calltree"].initialized,
"The js-calltree detail view should still not have been created yet.");
ok(!DetailsView.components["js-flamegraph"].initialized,
"The js-flamegraph detail view should still not have been created yet.");
ok(!DetailsView.components["memory-calltree"].initialized,
"The memory-calltree detail view should still not have been created yet.");
ok(!DetailsView.components["memory-flamegraph"].initialized,
"The memory-flamegraph detail view should still not have been created yet.");
yield DetailsView.selectView("js-calltree");
is(PerformanceView.getState(), "recorded",
"The current state of the performance panel view is still 'recorded'.");
ok(DetailsView.components["js-calltree"].initialized,
"The js-calltree detail view should still have been created now.");
ok(!DetailsView.components["js-flamegraph"].initialized,
"The js-flamegraph detail view should still not have been created yet.");
ok(!DetailsView.components["memory-calltree"].initialized,
"The memory-calltree detail view should still not have been created yet.");
ok(!DetailsView.components["memory-flamegraph"].initialized,
"The memory-flamegraph detail view should still not have been created yet.");
yield DetailsView.selectView("memory-calltree");
is(PerformanceView.getState(), "recorded",
"The current state of the performance panel view is still 'recorded'.");
ok(DetailsView.components["js-calltree"].initialized,
"The js-calltree detail view should still register as being created.");
ok(!DetailsView.components["js-flamegraph"].initialized,
"The js-flamegraph detail view should still not have been created yet.");
ok(DetailsView.components["memory-calltree"].initialized,
"The memory-calltree detail view should still have been created now.");
ok(!DetailsView.components["memory-flamegraph"].initialized,
"The memory-flamegraph detail view should still not have been created yet.");
yield teardown(panel);
finish();
}

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

@ -7,8 +7,21 @@
let test = Task.async(function*() {
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
let { EVENTS, PerformanceController, DetailsSubview } = panel.panelWin;
let { EVENTS, PerformanceController, DetailsView, DetailsSubview } = panel.panelWin;
// Enable memory to test the memory-calltree and memory-flamegraph.
Services.prefs.setBoolPref(MEMORY_PREF, true);
// Cycle through all the views to initialize them, otherwise we can't use
// `waitForWidgetsRendered`. The waterfall is shown by default, but all the
// other views are created lazily, so won't emit any events.
yield DetailsView.selectView("js-calltree");
yield DetailsView.selectView("js-flamegraph");
yield DetailsView.selectView("memory-calltree");
yield DetailsView.selectView("memory-flamegraph");
// Need to allow widgets to be updated while hidden, otherwise we can't use
// `waitForWidgetsRendered`.
DetailsSubview.canUpdateWhileHidden = true;
yield startRecording(panel);

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

@ -8,8 +8,21 @@
let test = Task.async(function*() {
let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL);
let { EVENTS, PerformanceController, DetailsSubview } = panel.panelWin;
let { EVENTS, PerformanceController, DetailsView, DetailsSubview } = panel.panelWin;
// Enable memory to test the memory-calltree and memory-flamegraph.
Services.prefs.setBoolPref(MEMORY_PREF, true);
// Cycle through all the views to initialize them, otherwise we can't use
// `waitForWidgetsRendered`. The waterfall is shown by default, but all the
// other views are created lazily, so won't emit any events.
yield DetailsView.selectView("js-calltree");
yield DetailsView.selectView("js-flamegraph");
yield DetailsView.selectView("memory-calltree");
yield DetailsView.selectView("memory-flamegraph");
// Need to allow widgets to be updated while hidden, otherwise we can't use
// `waitForWidgetsRendered`.
DetailsSubview.canUpdateWhileHidden = true;
yield startRecording(panel);

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

@ -255,12 +255,10 @@ function* startRecording(panel) {
ok(!button.hasAttribute("checked"),
"The record button should not be checked yet.");
ok(!button.hasAttribute("locked"),
"The record button should not be locked yet.");
click(win, button);
yield clicked;
ok(button.hasAttribute("checked"),
@ -269,7 +267,16 @@ function* startRecording(panel) {
"The record button should be locked.");
yield willStart;
let stateChanged = once(win.PerformanceView, win.EVENTS.UI_STATE_CHANGED);
yield hasStarted;
let overviewRendered = once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED);
yield stateChanged;
yield overviewRendered;
is(win.PerformanceView.getState(), "recording",
"The current state is 'recording'.");
ok(button.hasAttribute("checked"),
"The record button should still be checked.");
@ -290,7 +297,6 @@ function* stopRecording(panel) {
"The record button should not be locked yet.");
click(win, button);
yield clicked;
ok(!button.hasAttribute("checked"),
@ -299,7 +305,16 @@ function* stopRecording(panel) {
"The record button should be locked.");
yield willStop;
let stateChanged = once(win.PerformanceView, win.EVENTS.UI_STATE_CHANGED);
yield hasStopped;
let overviewRendered = once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED);
yield stateChanged;
yield overviewRendered;
is(win.PerformanceView.getState(), "recorded",
"The current state is 'recorded'.");
ok(!button.hasAttribute("checked"),
"The record button should not be checked.");
@ -313,7 +328,9 @@ function waitForWidgetsRendered(panel) {
OverviewView,
WaterfallView,
JsCallTreeView,
JsFlameGraphView
JsFlameGraphView,
MemoryCallTreeView,
MemoryFlameGraphView,
} = panel.panelWin;
return Promise.all([
@ -323,7 +340,9 @@ function waitForWidgetsRendered(panel) {
once(OverviewView, EVENTS.OVERVIEW_RENDERED),
once(WaterfallView, EVENTS.WATERFALL_RENDERED),
once(JsCallTreeView, EVENTS.JS_CALL_TREE_RENDERED),
once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED)
once(JsFlameGraphView, EVENTS.JS_FLAMEGRAPH_RENDERED),
once(MemoryCallTreeView, EVENTS.MEMORY_CALL_TREE_RENDERED),
once(MemoryFlameGraphView, EVENTS.MEMORY_FLAMEGRAPH_RENDERED),
]);
}

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

@ -102,11 +102,10 @@ let DetailsSubview = {
/**
* Fired when a preference in `devtools.performance.ui.` is changed.
*/
_onPrefChanged: function (_, prefName, value) {
_onPrefChanged: function (_, prefName) {
// All detail views require a recording to be complete, so do not
// attempt to render if recording is in progress or does not exist.
let recording = PerformanceController.getCurrentRecording();
if (!recording || recording.isRecording()) {
return;
}

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

@ -35,12 +35,9 @@ let DetailsView = {
button.addEventListener("command", this._onViewToggle);
}
for (let [_, { view }] of Iterator(this.components)) {
yield view.initialize();
}
this.selectView(DEFAULT_DETAILS_SUBVIEW);
yield this.selectView(DEFAULT_DETAILS_SUBVIEW);
this.setAvailableViews();
PerformanceController.on(EVENTS.PREF_CHANGED, this.setAvailableViews);
}),
@ -52,9 +49,10 @@ let DetailsView = {
button.removeEventListener("command", this._onViewToggle);
}
for (let [_, { view }] of Iterator(this.components)) {
yield view.destroy();
for (let [_, component] of Iterator(this.components)) {
component.initialized && (yield component.view.destroy());
}
PerformanceController.off(EVENTS.PREF_CHANGED, this.setAvailableViews);
}),
@ -71,7 +69,8 @@ let DetailsView = {
let value = PerformanceController.getPref(pref);
$(`toolbarbutton[data-view=${name}]`).hidden = !value;
// If the view is currently selected and not enabled, go back to the default view
// If the view is currently selected and not enabled, go back to the
// default view.
if (!value && this.isViewSelected(view)) {
this.selectView(DEFAULT_DETAILS_SUBVIEW);
}
@ -85,8 +84,11 @@ let DetailsView = {
* @param String viewName
* Name of the view to be shown.
*/
selectView: function (viewName) {
this.el.selectedPanel = $("#" + this.components[viewName].id);
selectView: Task.async(function *(viewName) {
let component = this.components[viewName];
this.el.selectedPanel = $("#" + component.id);
yield this._whenViewInitialized(component);
for (let button of $$("toolbarbutton[data-view]", this.toolbar)) {
if (button.getAttribute("data-view") === viewName) {
@ -97,7 +99,7 @@ let DetailsView = {
}
this.emit(EVENTS.DETAILS_VIEW_SELECTED, viewName);
},
}),
/**
* Checks if the provided view is currently selected.
@ -133,6 +135,30 @@ let DetailsView = {
return this.whenViewSelected(viewObject);
}),
/**
* Initializes a subview if it wasn't already set up, and makes sure
* it's populated with recording data if there is some available.
*
* @param object component
* A component descriptor from DetailsView.components
*/
_whenViewInitialized: Task.async(function *(component) {
if (component.initialized) {
return;
}
component.initialized = true;
yield component.view.initialize();
// If this view is initialized *after* a recording is shown, it won't display
// any data. Make sure it's populated by setting `shouldUpdateWhenShown`.
// All detail views require a recording to be complete, so do not
// attempt to render if recording is in progress or does not exist.
let recording = PerformanceController.getCurrentRecording();
if (recording && !recording.isRecording()) {
component.view.shouldUpdateWhenShown = true;
}
}),
/**
* Called when a view button is clicked.
*/

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

@ -25,7 +25,7 @@ let OverviewView = {
/**
* Sets up the view with event binding.
*/
initialize: Task.async(function *() {
initialize: function () {
this._onRecordingWillStart = this._onRecordingWillStart.bind(this);
this._onRecordingStarted = this._onRecordingStarted.bind(this);
this._onRecordingWillStop = this._onRecordingWillStop.bind(this);
@ -35,39 +35,25 @@ let OverviewView = {
this._onGraphSelecting = this._onGraphSelecting.bind(this);
this._onPrefChanged = this._onPrefChanged.bind(this);
yield this._showMarkersGraph();
yield this._showMemoryGraph();
yield this._showFramerateGraph();
this.markersOverview.on("selecting", this._onGraphSelecting);
PerformanceController.on(EVENTS.RECORDING_WILL_START, this._onRecordingWillStart);
// Toggle the initial state of memory and framerate graph based off of
// the prefs.
// Toggle the initial visibility of memory and framerate graph containers
// based off of prefs.
$("#memory-overview").hidden = !PerformanceController.getPref("enable-memory");
$("#time-framerate").hidden = !PerformanceController.getPref("enable-framerate");
PerformanceController.on(EVENTS.PREF_CHANGED, this._onPrefChanged);
PerformanceController.on(EVENTS.RECORDING_WILL_START, this._onRecordingWillStart);
PerformanceController.on(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
PerformanceController.on(EVENTS.RECORDING_WILL_STOP, this._onRecordingWillStop);
PerformanceController.on(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
PerformanceController.on(EVENTS.RECORDING_SELECTED, this._onRecordingSelected);
// Populate this overview with some dummy initial data.
this.markersOverview.setData({ duration: 1000, markers: [] });
this.memoryOverview.setData([]);
this.framerateGraph.setData([]);
}),
},
/**
* Unbinds events.
*/
destroy: function () {
this.markersOverview.off("selecting", this._onGraphSelecting);
PerformanceController.off(EVENTS.RECORDING_WILL_START, this._onRecordingWillStart);
PerformanceController.off(EVENTS.PREF_CHANGED, this._onPrefChanged);
PerformanceController.off(EVENTS.RECORDING_WILL_START, this._onRecordingWillStart);
PerformanceController.off(EVENTS.RECORDING_STARTED, this._onRecordingStarted);
PerformanceController.off(EVENTS.RECORDING_WILL_STOP, this._onRecordingWillStop);
PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStopped);
@ -111,43 +97,64 @@ let OverviewView = {
},
/**
* Sets up the framerate graph.
* Sets up the markers overivew graph, if needed.
*
* @return object
* A promise resolved to `true` when the graph was initialized.
*/
_showFramerateGraph: Task.async(function *() {
this.framerateGraph = new LineGraphWidget($("#time-framerate"), {
metric: L10N.getStr("graphs.fps")
});
this.framerateGraph.fixedHeight = FRAMERATE_GRAPH_HEIGHT;
yield this.framerateGraph.ready();
}),
/**
* Sets up the markers overivew graph.
*/
_showMarkersGraph: Task.async(function *() {
_markersGraphAvailable: Task.async(function *() {
if (this.markersOverview) {
yield this.markersOverview.ready();
return true;
}
this.markersOverview = new MarkersOverview($("#markers-overview"), TIMELINE_BLUEPRINT);
this.markersOverview.headerHeight = MARKERS_GRAPH_HEADER_HEIGHT;
this.markersOverview.rowHeight = MARKERS_GRAPH_ROW_HEIGHT;
this.markersOverview.groupPadding = MARKERS_GROUP_VERTICAL_PADDING;
this.markersOverview.on("selecting", this._onGraphSelecting);
yield this.markersOverview.ready();
return true;
}),
/**
* Sets up the memory overview graph.
* Sets up the memory overview graph, if allowed and needed.
*
* @return object
* A promise resolved to `true` if the graph was initialized and is
* ready to use, `false` if the graph is disabled.
*/
_showMemoryGraph: Task.async(function *() {
_memoryGraphAvailable: Task.async(function *() {
if (!PerformanceController.getPref("enable-memory")) {
return false;
}
if (this.memoryOverview) {
yield this.memoryOverview.ready();
return true;
}
this.memoryOverview = new MemoryOverview($("#memory-overview"));
this.memoryOverview.fixedHeight = MEMORY_GRAPH_HEIGHT;
yield this.memoryOverview.ready();
CanvasGraphUtils.linkAnimation(this.markersOverview, this.memoryOverview);
CanvasGraphUtils.linkSelection(this.markersOverview, this.memoryOverview);
return true;
}),
/**
* Sets up the framerate graph.
* Sets up the framerate graph, if allowed and needed.
*
* @return object
* A promise resolved to `true` if the graph was initialized and is
* ready to use, `false` if the graph is disabled.
*/
_showFramerateGraph: Task.async(function *() {
_framerateGraphAvailable: Task.async(function *() {
if (!PerformanceController.getPref("enable-framerate")) {
return false;
}
if (this.framerateGraph) {
yield this.framerateGraph.ready();
return true;
}
let metric = L10N.getStr("graphs.fps");
this.framerateGraph = new LineGraphWidget($("#time-framerate"), { metric });
this.framerateGraph.fixedHeight = FRAMERATE_GRAPH_HEIGHT;
@ -155,6 +162,7 @@ let OverviewView = {
CanvasGraphUtils.linkAnimation(this.markersOverview, this.framerateGraph);
CanvasGraphUtils.linkSelection(this.markersOverview, this.framerateGraph);
return true;
}),
/**
@ -171,16 +179,16 @@ let OverviewView = {
let timestamps = recording.getTicks();
// Empty or older recordings might yield no markers, memory or timestamps.
if (markers) {
if (markers && (yield this._markersGraphAvailable())) {
this.markersOverview.setData({ markers, duration });
this.emit(EVENTS.MARKERS_GRAPH_RENDERED);
}
if (memory) {
if (memory && (yield this._memoryGraphAvailable())) {
this.memoryOverview.dataDuration = duration;
this.memoryOverview.setData(memory);
this.emit(EVENTS.MEMORY_GRAPH_RENDERED);
}
if (timestamps) {
if (timestamps && (yield this._framerateGraphAvailable())) {
this.framerateGraph.dataDuration = duration;
yield this.framerateGraph.setDataFromTimestamps(timestamps, resolution);
this.emit(EVENTS.FRAMERATE_GRAPH_RENDERED);
@ -200,6 +208,17 @@ let OverviewView = {
this._prepareNextTick();
}),
/**
* Called to refresh the timer to keep firing _onRecordingTick.
*/
_prepareNextTick: function () {
// Check here to see if there's still a _timeoutId, incase
// `stop` was called before the _prepareNextTick call was executed.
if (this._timeoutId) {
this._timeoutId = setTimeout(this._onRecordingTick, OVERVIEW_UPDATE_INTERVAL);
}
},
/**
* Fired when the graph selection has changed. Called by
* mouseup and scroll events.
@ -219,24 +238,13 @@ let OverviewView = {
}
},
/**
* Called to refresh the timer to keep firing _onRecordingTick.
*/
_prepareNextTick: function () {
// Check here to see if there's still a _timeoutId, incase
// `stop` was called before the _prepareNextTick call was executed.
if (this._timeoutId) {
this._timeoutId = setTimeout(this._onRecordingTick, OVERVIEW_UPDATE_INTERVAL);
}
},
/**
* Called when recording will start.
*/
_onRecordingWillStart: function (_, recording) {
this._checkSelection(recording);
this.framerateGraph.dropSelection();
},
_onRecordingWillStart: Task.async(function* (_, recording) {
yield this._checkSelection(recording);
this.markersOverview.dropSelection();
}),
/**
* Called when recording actually starts.
@ -256,40 +264,50 @@ let OverviewView = {
/**
* Called when recording actually stops.
*/
_onRecordingStopped: function (_, recording) {
this._checkSelection(recording);
_onRecordingStopped: Task.async(function* (_, recording) {
this.render(FRAMERATE_GRAPH_HIGH_RES_INTERVAL);
},
yield this._checkSelection(recording);
}),
/**
* Called when a new recording is selected.
*/
_onRecordingSelected: function (_, recording) {
_onRecordingSelected: Task.async(function* (_, recording) {
if (!recording) {
return;
}
this.markersOverview.dropSelection();
this._checkSelection(recording);
// If timeout exists, we have something recording, so
// this will still tick away at rendering. Otherwise, force a render.
if (!this._timeoutId) {
this.render(FRAMERATE_GRAPH_HIGH_RES_INTERVAL);
yield this.render(FRAMERATE_GRAPH_HIGH_RES_INTERVAL);
}
},
yield this._checkSelection(recording);
this.markersOverview.dropSelection();
}),
_checkSelection: function (recording) {
/**
* Makes sure the selection is enabled or disabled in all the graphs,
* based on whether a recording currently exists and is not in progress.
*/
_checkSelection: Task.async(function* (recording) {
let selectionEnabled = !recording.isRecording();
this.markersOverview.selectionEnabled = selectionEnabled;
this.memoryOverview.selectionEnabled = selectionEnabled;
this.framerateGraph.selectionEnabled = selectionEnabled;
},
if (yield this._markersGraphAvailable()) {
this.markersOverview.selectionEnabled = selectionEnabled;
}
if (yield this._memoryGraphAvailable()) {
this.memoryOverview.selectionEnabled = selectionEnabled;
}
if (yield this._framerateGraphAvailable()) {
this.framerateGraph.selectionEnabled = selectionEnabled;
}
}),
/**
* Called whenever a preference in `devtools.performance.ui.` changes. Used
* to toggle the visibility of memory and framerate graphs.
*/
_onPrefChanged: function (_, prefName, value) {
_onPrefChanged: function (_, prefName) {
if (prefName === "enable-memory") {
$("#memory-overview").hidden = !PerformanceController.getPref("enable-memory");
}