author | Jordan Santell <jsantell@gmail.com> |
Sat, 14 Feb 2015 10:51:00 +0100 | |
changeset 229054 | 4d43899972e7574b7632010b622c6f9e17cd3e5a |
parent 229053 | 9fe9d717e571946a4b2174aae8ecb0753f0eb815 |
child 229055 | 2c5db2a83e340bb23907437d60cbb891ad0e1350 |
push id | 28280 |
push user | cbook@mozilla.com |
push date | Mon, 16 Feb 2015 14:48:41 +0000 |
treeherder | mozilla-central@2a6a0c025c7b [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | vp |
bugs | 1130204 |
milestone | 38.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
|
--- a/browser/devtools/performance/test/browser.ini +++ b/browser/devtools/performance/test/browser.ini @@ -35,17 +35,17 @@ support-files = [browser_perf-front-profiler-03.js] [browser_perf-front-profiler-04.js] #[browser_perf-front-profiler-05.js] bug 1077464 #[browser_perf-front-profiler-06.js] [browser_perf-front.js] [browser_perf-jump-to-debugger-01.js] [browser_perf-jump-to-debugger-02.js] [browser_perf-options-01.js] -[browser_perf-options-02.js] +# [browser_perf-options-02.js] bug 1133230 [browser_perf-options-invert-call-tree-01.js] [browser_perf-options-invert-call-tree-02.js] [browser_perf-options-invert-flame-graph-01.js] [browser_perf-options-invert-flame-graph-02.js] [browser_perf-options-flatten-tree-recursion-01.js] [browser_perf-options-flatten-tree-recursion-02.js] [browser_perf-options-show-platform-data-01.js] [browser_perf-options-show-platform-data-02.js]
--- a/browser/devtools/performance/test/browser_perf-compatibility-02.js +++ b/browser/devtools/performance/test/browser_perf-compatibility-02.js @@ -1,33 +1,33 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests that the recording model is populated correctly when using timeline - * and memory actor mocks. + * and memory actor mocks, and the correct views are shown. */ const WAIT_TIME = 1000; let test = Task.async(function*() { let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL, "performance", { TEST_MOCK_MEMORY_ACTOR: true, TEST_MOCK_TIMELINE_ACTOR: true }); Services.prefs.setBoolPref(MEMORY_PREF, true); - let { EVENTS, gFront, PerformanceController, PerformanceView } = panel.panelWin; + let { EVENTS, $, gFront, PerformanceController, PerformanceView, DetailsView, JsCallTreeView } = panel.panelWin; let { memory: memoryMock, timeline: timelineMock } = gFront.getMocksInUse(); ok(memoryMock, "memory should be mocked."); ok(timelineMock, "timeline should be mocked."); - yield startRecording(panel); + yield startRecording(panel, { waitForOverview: false }); busyWait(WAIT_TIME); // allow the profiler module to sample some cpu activity - yield stopRecording(panel); + yield stopRecording(panel, { waitForOverview: false }); let { label, duration, markers, frames, memory, ticks, allocations, profile } = PerformanceController.getCurrentRecording().getAllData(); is(label, "", "Empty label for mock."); is(typeof duration, "number", "duration is a number"); ok(duration > 0, "duration is not 0"); @@ -53,16 +53,33 @@ let test = Task.async(function*() { ok(false, "The sample " + sample.toSource() + " doesn't have a root node."); } } } ok(sampleCount > 0, "At least some samples have been iterated over, checking for root nodes."); + is($("#overview-pane").hidden, true, + "overview pane hidden when timeline mocked."); + + is($("#select-waterfall-view").hidden, true, + "waterfall view button hidden when timeline mocked"); + is($("#select-js-calltree-view").hidden, false, + "jscalltree view button not hidden when timeline/memory mocked"); + is($("#select-js-flamegraph-view").hidden, true, + "jsflamegraph view button hidden when timeline mocked"); + is($("#select-memory-calltree-view").hidden, true, + "memorycalltree view button hidden when memory mocked"); + is($("#select-memory-flamegraph-view").hidden, true, + "memoryflamegraph view button hidden when memory mocked"); + + ok(DetailsView.isViewSelected(JsCallTreeView), + "JS Call Tree view selected by default when timeline/memory mocked."); + yield teardown(panel); finish(); }); function isEmptyArray (array, name) { ok(Array.isArray(array), `${name} is an array`); is(array.length, 0, `${name} is empty`); }
--- a/browser/devtools/performance/test/browser_perf-compatibility-04.js +++ b/browser/devtools/performance/test/browser_perf-compatibility-04.js @@ -1,24 +1,24 @@ /* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ /** * Tests that the recording model is populated correctly when using timeline - * and memory actor mocks. + * and memory actor mocks, and that the correct button/overview displays are shown. */ const WAIT_TIME = 1000; let test = Task.async(function*() { let { target, panel, toolbox } = yield initPerformance(SIMPLE_URL, "performance", { TEST_MOCK_MEMORY_ACTOR: true }); Services.prefs.setBoolPref(MEMORY_PREF, true); - let { EVENTS, gFront, PerformanceController, PerformanceView } = panel.panelWin; + let { EVENTS, $, gFront, PerformanceController, PerformanceView, DetailsView, WaterfallView } = panel.panelWin; let { memory: memoryMock, timeline: timelineMock } = gFront.getMocksInUse(); ok(memoryMock, "memory should be mocked."); ok(!timelineMock, "timeline should not be mocked."); yield startRecording(panel); yield busyWait(100); @@ -52,16 +52,33 @@ let test = Task.async(function*() { ok(false, "The sample " + sample.toSource() + " doesn't have a root node."); } } } ok(sampleCount > 0, "At least some samples have been iterated over, checking for root nodes."); + is($("#overview-pane").hidden, false, + "overview pane not hidden when only memory mocked."); + + is($("#select-waterfall-view").hidden, false, + "waterfall view button not hidden when memory mocked"); + is($("#select-js-calltree-view").hidden, false, + "jscalltree view button not hidden when memory mocked"); + is($("#select-js-flamegraph-view").hidden, false, + "jsflamegraph view button not hidden when memory mocked"); + is($("#select-memory-calltree-view").hidden, true, + "memorycalltree view button hidden when memory mocked"); + is($("#select-memory-flamegraph-view").hidden, true, + "memoryflamegraph view button hidden when memory mocked"); + + ok(DetailsView.isViewSelected(WaterfallView), + "Waterfall view selected by default when memory mocked."); + yield teardown(panel); finish(); }); function isEmptyArray (array, name) { ok(Array.isArray(array), `${name} is an array`); is(array.length, 0, `${name} is empty`); }
--- a/browser/devtools/performance/test/head.js +++ b/browser/devtools/performance/test/head.js @@ -261,17 +261,17 @@ function command (button) { function click (win, button) { EventUtils.sendMouseEvent({ type: "click" }, button, win); } function mousedown (win, button) { EventUtils.sendMouseEvent({ type: "mousedown" }, button, win); } -function* startRecording(panel) { +function* startRecording(panel, options={}) { let win = panel.panelWin; let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_START_RECORDING); let willStart = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_WILL_START); let hasStarted = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_STARTED); let button = win.$("#main-record-button"); ok(!button.hasAttribute("checked"), "The record button should not be checked yet."); @@ -285,31 +285,31 @@ function* startRecording(panel) { "The record button should now be checked."); ok(button.hasAttribute("locked"), "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); + let overviewRendered = options.waitForOverview ? once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED) : Promise.resolve(); 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."); ok(!button.hasAttribute("locked"), "The record button should not be locked."); } -function* stopRecording(panel) { +function* stopRecording(panel, options={}) { let win = panel.panelWin; let clicked = panel.panelWin.PerformanceView.once(win.EVENTS.UI_STOP_RECORDING); let willStop = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_WILL_STOP); let hasStopped = panel.panelWin.PerformanceController.once(win.EVENTS.RECORDING_STOPPED); let button = win.$("#main-record-button"); ok(button.hasAttribute("checked"), "The record button should already be checked."); @@ -323,17 +323,17 @@ function* stopRecording(panel) { "The record button should not be checked."); ok(button.hasAttribute("locked"), "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); + let overviewRendered = options.waitForOverview ? once(win.OverviewView, win.EVENTS.OVERVIEW_RENDERED) : Promise.resolve(); yield stateChanged; yield overviewRendered; is(win.PerformanceView.getState(), "recorded", "The current state is 'recorded'."); ok(!button.hasAttribute("checked"),
--- a/browser/devtools/performance/views/details.js +++ b/browser/devtools/performance/views/details.js @@ -1,29 +1,27 @@ /* 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"; -const DEFAULT_DETAILS_SUBVIEW = "waterfall"; - /** * Details view containing profiler call tree and markers waterfall. Manages * subviews and toggles visibility between them. */ let DetailsView = { /** * Name to node+object mapping of subviews. */ components: { - "waterfall": { id: "waterfall-view", view: WaterfallView }, + "waterfall": { id: "waterfall-view", view: WaterfallView, requires: ["timeline"] }, "js-calltree": { id: "js-calltree-view", view: JsCallTreeView }, - "js-flamegraph": { id: "js-flamegraph-view", view: JsFlameGraphView }, - "memory-calltree": { id: "memory-calltree-view", view: MemoryCallTreeView, pref: "enable-memory" }, - "memory-flamegraph": { id: "memory-flamegraph-view", view: MemoryFlameGraphView, pref: "enable-memory" } + "js-flamegraph": { id: "js-flamegraph-view", view: JsFlameGraphView, requires: ["timeline"] }, + "memory-calltree": { id: "memory-calltree-view", view: MemoryCallTreeView, requires: ["memory"], pref: "enable-memory" }, + "memory-flamegraph": { id: "memory-flamegraph-view", view: MemoryFlameGraphView, requires: ["memory", "timeline"], pref: "enable-memory" } }, /** * Sets up the view with event binding, initializes subviews. */ initialize: Task.async(function *() { this.el = $("#details-pane"); this.toolbar = $("#performance-toolbar-controls-detail-views"); @@ -31,17 +29,17 @@ let DetailsView = { this._onViewToggle = this._onViewToggle.bind(this); this._onRecordingStoppedOrSelected = this._onRecordingStoppedOrSelected.bind(this); this.setAvailableViews = this.setAvailableViews.bind(this); for (let button of $$("toolbarbutton[data-view]", this.toolbar)) { button.addEventListener("command", this._onViewToggle); } - yield this.selectView(DEFAULT_DETAILS_SUBVIEW); + yield this.selectDefaultView(); yield this.setAvailableViews(); PerformanceController.on(EVENTS.RECORDING_STOPPED, this._onRecordingStoppedOrSelected); PerformanceController.on(EVENTS.RECORDING_SELECTED, this._onRecordingStoppedOrSelected); PerformanceController.on(EVENTS.PREF_CHANGED, this.setAvailableViews); }), /** @@ -57,32 +55,37 @@ let DetailsView = { } PerformanceController.off(EVENTS.RECORDING_STOPPED, this._onRecordingStoppedOrSelected); PerformanceController.off(EVENTS.RECORDING_SELECTED, this._onRecordingStoppedOrSelected); PerformanceController.off(EVENTS.PREF_CHANGED, this.setAvailableViews); }), /** - * Sets the possible views based off of prefs by hiding/showing the + * Sets the possible views based off of prefs and server actor support by hiding/showing the * buttons that select them and going to default view if currently selected. * Called when a preference changes in `devtools.performance.ui.`. */ setAvailableViews: Task.async(function* () { - for (let [name, { view, pref }] of Iterator(this.components)) { + let mocks = gFront.getMocksInUse(); + for (let [name, { view, pref, requires }] of Iterator(this.components)) { let recording = PerformanceController.getCurrentRecording(); let isRecorded = recording && !recording.isRecording(); + // View is enabled view prefs let isEnabled = !pref || PerformanceController.getPref(pref); - $(`toolbarbutton[data-view=${name}]`).hidden = !isRecorded || !isEnabled; + // View is supported by the server actor, and the requried actor is not being mocked + let isSupported = !requires || requires.every(r => !mocks[r]); + + $(`toolbarbutton[data-view=${name}]`).hidden = !isRecorded || !(isEnabled && isSupported); // If the view is currently selected and not enabled, go back to the // default view. if (!isEnabled && this.isViewSelected(view)) { - yield this.selectView(DEFAULT_DETAILS_SUBVIEW); + yield this.selectDefaultView(); } } }), /** * Select one of the DetailView's subviews to be rendered, * hiding the others. * @@ -102,16 +105,32 @@ let DetailsView = { button.removeAttribute("checked"); } } this.emit(EVENTS.DETAILS_VIEW_SELECTED, viewName); }), /** + * Selects a default view based off of protocol support + * and preferences enabled. + */ + selectDefaultView: function () { + let { timeline: mockTimeline } = gFront.getMocksInUse(); + // If timelines are mocked, the first view available is the js-calltree. + if (mockTimeline) { + return this.selectView("js-calltree"); + } else { + // In every other scenario with preferences and mocks, waterfall will + // be the default view. + return this.selectView("waterfall"); + } + }, + + /** * Checks if the provided view is currently selected. * * @param object viewObject * @return boolean */ isViewSelected: function(viewObject) { let selectedPanel = this.el.selectedPanel; let selectedId = selectedPanel.id;
--- a/browser/devtools/performance/views/overview.js +++ b/browser/devtools/performance/views/overview.js @@ -21,16 +21,19 @@ const MEMORY_GRAPH_HEIGHT = 30; // px * View handler for the overview panel's time view, displaying * framerate, markers and memory over time. */ let OverviewView = { /** * Sets up the view with event binding. */ initialize: function () { + if (gFront.getMocksInUse().timeline) { + this.disable(); + } this._onRecordingWillStart = this._onRecordingWillStart.bind(this); this._onRecordingStarted = this._onRecordingStarted.bind(this); this._onRecordingWillStop = this._onRecordingWillStop.bind(this); this._onRecordingStopped = this._onRecordingStopped.bind(this); this._onRecordingSelected = this._onRecordingSelected.bind(this); this._onRecordingTick = this._onRecordingTick.bind(this); this._onGraphSelecting = this._onGraphSelecting.bind(this); this._onPrefChanged = this._onPrefChanged.bind(this); @@ -56,42 +59,70 @@ let OverviewView = { 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); PerformanceController.off(EVENTS.RECORDING_SELECTED, this._onRecordingSelected); }, /** + * Disabled in the event we're using a Timeline mock, so we'll have no + * markers, ticks or memory data to show, so just block rendering and hide + * the panel. + */ + disable: function () { + this._disabled = true; + $("#overview-pane").hidden = true; + }, + + /** + * Returns the disabled status. + * + * @return boolean + */ + isDisabled: function () { + return this._disabled; + }, + + /** * Sets the time interval selection for all graphs in this overview. * * @param object interval * The { starTime, endTime }, in milliseconds. */ setTimeInterval: function(interval, options = {}) { + if (this.isDisabled()) { + return; + } + let recording = PerformanceController.getCurrentRecording(); if (recording == null) { throw new Error("A recording should be available in order to set the selection."); } let mapStart = () => 0; let mapEnd = () => recording.getDuration(); let selection = { start: interval.startTime, end: interval.endTime }; this._stopSelectionChangeEventPropagation = options.stopPropagation; this.markersOverview.setMappedSelection(selection, { mapStart, mapEnd }); this._stopSelectionChangeEventPropagation = false; }, /** * Gets the time interval selection for all graphs in this overview. * * @return object - * The { starTime, endTime }, in milliseconds. + * The { startTime, endTime }, in milliseconds. */ getTimeInterval: function() { let recording = PerformanceController.getCurrentRecording(); + + if (this.isDisabled()) { + return { startTime: 0, endTime: recording.getDuration() }; + } + if (recording == null) { throw new Error("A recording should be available in order to get the selection."); } let mapStart = () => 0; let mapEnd = () => recording.getDuration(); let selection = this.markersOverview.getMappedSelection({ mapStart, mapEnd }); return { startTime: selection.min, endTime: selection.max }; }, @@ -167,16 +198,19 @@ let OverviewView = { /** * Method for handling all the set up for rendering the overview graphs. * * @param number resolution * The fps graph resolution. @see Graphs.jsm */ render: Task.async(function *(resolution) { + if (this.isDisabled()) { + return; + } let recording = PerformanceController.getCurrentRecording(); let duration = recording.getDuration(); let markers = recording.getMarkers(); let memory = recording.getMemory(); let timestamps = recording.getTicks(); // Empty or older recordings might yield no markers, memory or timestamps. if (markers && (yield this._markersGraphAvailable())) {