author | Ryan VanderMeulen <ryanvm@gmail.com> |
Wed, 03 Jun 2015 16:12:10 -0400 | |
changeset 247130 | dc4023d54436f3a1fd4c93adfdc595aedab5b082 |
parent 247129 | cd451afd6400e9ca96fd9a6062bda0bff19f6af8 |
child 247131 | 813e37cf69e3adc4571ef15a83af234c172891bf |
push id | 28854 |
push user | ryanvm@gmail.com |
push date | Thu, 04 Jun 2015 13:24:20 +0000 |
treeherder | mozilla-central@5b4c240e1a36 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1169439 |
milestone | 41.0a1 |
backs out | b617a57d6bf1a18d3f487be2f989feef3dc4a072 |
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/modules/logic/marker-utils.js +++ b/browser/devtools/performance/modules/logic/marker-utils.js @@ -275,83 +275,69 @@ const DOM = { return container; } }; /** * A series of collapsers used by the blueprint. These functions are * invoked on a moving window of two markers. - * - * A function determining how markers are collapsed together. - * Invoked with 3 arguments: the current parent marker, the - * current marker and a method for peeking i markers ahead. If - * nothing is returned, the marker is added as a standalone entry - * in the waterfall. Otherwise, an object needs to be returned - * with the following properties: - * - toParent: The marker to be made a new parent. Can use the current - * marker, becoming a parent itself, or make a new marker-esque - * object. - * - collapse: Whether or not this current marker should be nested within - * the current parent. - * - finalize: Whether or not the current parent should be finalized and popped - * off the stack. */ + const CollapseFunctions = { - /** - * Combines similar markers that are consecutive into a meta marker. - */ identical: function (parent, curr, peek) { - let next = peek(1); // If there is a parent marker currently being filled and the current marker // should go into the parent marker, make it so. if (parent && parent.name == curr.name) { - let finalize = next && next.name !== curr.name; - return { collapse: true, finalize }; + return { toParent: parent.name }; } // Otherwise if the current marker is the same type as the next marker type, // create a new parent marker containing the current marker. + let next = peek(1); if (next && curr.name == next.name) { - return { toParent: { name: curr.name, start: curr.start }, collapse: true }; + return { toParent: curr.name }; } }, - /** - * Combines similar markers that are close to each other in time into a meta marker. - */ adjacent: function (parent, curr, peek) { let next = peek(1); if (next && (next.start < curr.end || next.start - curr.end <= 10 /* ms */)) { return CollapseFunctions.identical(parent, curr, peek); } }, - /** - * Folds this marker in parent marker if parent marker fully eclipses - * the current markers' time. - */ - child: function (parent, curr, peek) { + DOMtoDOMJS: function (parent, curr, peek) { + // If the next marker is a JavaScript marker, create a new meta parent marker + // containing the current marker. let next = peek(1); - // If this marker is consumed by current parent, collapse - if (parent && curr.end <= parent.end) { - let finalize = next && next.end > parent.end; - return { collapse: true, finalize }; + if (next && next.name == "Javascript") { + return { + forceNew: true, + toParent: "meta::DOMEvent+JS", + withData: { + type: curr.type, + eventPhase: curr.eventPhase + }, + }; } }, - /** - * Turns this marker into a parent marker if the next marker - * is fully eclipsed by the current marker. - */ - parent: function (parent, curr, peek) { - let next = peek(1); - // If the next marker is fully consumed by this marker, make - // it a parent (do not collapse, the marker becomes a parent). - if (next && curr.end >= next.end) { - return { toParent: curr }; + JStoDOMJS: function (parent, curr, peek) { + // If there is a parent marker currently being filled, and it's the one + // created from a `DOMEvent` via `collapseDOMIntoDOMJS`, then the current + // marker has to go into that one. + if (parent && parent.name == "meta::DOMEvent+JS") { + return { + forceEnd: true, + toParent: "meta::DOMEvent+JS", + withData: { + stack: curr.stack, + endStack: curr.endStack + }, + }; } }, }; /** * Mapping of JS marker causes to a friendlier form. Only * markers that are considered "from content" should be labeled here. */
--- a/browser/devtools/performance/modules/logic/waterfall-utils.js +++ b/browser/devtools/performance/modules/logic/waterfall-utils.js @@ -6,126 +6,136 @@ /** * Utility functions for collapsing markers into a waterfall. */ loader.lazyRequireGetter(this, "TIMELINE_BLUEPRINT", "devtools/performance/markers", true); /** - * Collapses markers into a tree-like structure. + * Collapses markers into a tree-like structure. Currently, this only goes + * one level deep. * @param object markerNode * @param array markersList - * @param ?object blueprint */ -function collapseMarkersIntoNode({ markerNode, markersList, blueprint }) { - let { getCurrentParentNode, collapseMarker, addParentNode, popParentNode } = createParentNodeFactory(markerNode); - blueprint = blueprint || TIMELINE_BLUEPRINT; +function collapseMarkersIntoNode({ markerNode, markersList }) { + let [getOrCreateParentNode, getCurrentParentNode, clearParentNode] = makeParentNodeFactory(); + let uid = 0; for (let i = 0, len = markersList.length; i < len; i++) { let curr = markersList[i]; + // Make sure all the markers have an assigned number id. This makes it + // easier to find them in a waterfall, for example. + curr.uid = ++uid; + let parentNode = getCurrentParentNode(); - let def = blueprint[curr.name]; - let collapse = def.collapseFunc || (() => null); + let blueprint = TIMELINE_BLUEPRINT[curr.name]; + let collapse = blueprint.collapseFunc || (() => null); let peek = distance => markersList[i + distance]; - let foundParent = false; + let collapseInfo = collapse(parentNode, curr, peek); - let collapseInfo = collapse(parentNode, curr, peek); if (collapseInfo) { - let { collapse, toParent, finalize } = collapseInfo; + let { toParent, withData, forceNew, forceEnd } = collapseInfo; - // If `toParent` is an object, use it as the next parent marker - if (typeof toParent === "object") { - addParentNode(toParent); + // If the `forceNew` prop is set on the collapse info, then a new parent + // marker needs to be created even if there is one already available. + if (forceNew) { + clearParentNode(); } + // If the `toParent` prop is set on the collapse info, then this marker + // can be collapsed into a higher-level parent marker. + if (toParent) { + let parentNode = getOrCreateParentNode({ + uid: ++uid, + owner: markerNode, + name: toParent, + start: curr.start, + end: curr.end + }); - if (collapse) { - collapseMarker(curr); - } + // A parent marker, even when created, will always have at least one + // child submarker (the one which caused it to be created). + parentNode.submarkers.push(curr); - // If the marker specifies this parent marker is full, - // pop it from the stack. - if (finalize) { - popParentNode(); + // Optionally, additional data may be stapled on this parent marker. + for (let key in withData) { + parentNode[key] = withData[key]; + } + } + // If the `forceEnd` prop is set on the collapse info, then the higher-level + // parent marker is full and should be finalized. + if (forceEnd) { + clearParentNode(); } } else { + clearParentNode(); markerNode.submarkers.push(curr); } } } /** - * Creates a parent marker, which functions like a regular marker, + * Creates an empty parent marker, which functions like a regular marker, * but is able to hold additional child markers. - * - * The marker is seeded with values from `marker`. - * @param object marker + * @param string name + * @param number uid + * @param number start [optional] + * @param number end [optional] * @return object */ -function makeParentMarkerNode (marker) { - let node = Object.create(null); - for (let prop in marker) { - node[prop] = marker[prop]; - } - node.submarkers = []; - return node; +function makeEmptyMarkerNode(name, uid, start, end) { + return { + name: name, + uid: uid, + start: start, + end: end, + submarkers: [] + }; } /** - * Takes a root marker node and creates a hash of functions used - * to manage the creation and nesting of additional parent markers. - * - * @param {object} root - * @return {object} + * Creates a factory for markers containing other markers. + * @return array[function] */ -function createParentNodeFactory (root) { - let parentMarkers = []; - let factory = { +function makeParentNodeFactory() { + let marker; + + return [ /** - * Pops the most recent parent node off the stack, finalizing it. - * Sets the `end` time based on the most recent child if not defined. + * Gets the current parent marker for the given marker name. If it doesn't + * exist, it creates it and appends it to another parent marker. + * @param object owner + * @param string name + * @param number start + * @param number end + * @return object */ - popParentNode: () => { - if (parentMarkers.length === 0) { - throw new Error("Cannot pop parent markers when none exist."); + function getOrCreateParentNode({ owner, name, uid, start, end }) { + if (marker && marker.name == name) { + marker.end = end; + return marker; + } else { + marker = makeEmptyMarkerNode(name, uid, start, end); + owner.submarkers.push(marker); + return marker; } - - let lastParent = parentMarkers.pop(); - // If this finished parent marker doesn't have an end time, - // so probably a synthesized marker, use the last marker's end time. - if (lastParent.end == void 0) { - lastParent.end = lastParent.submarkers[lastParent.submarkers.length - 1].end; - } - return lastParent; }, /** - * Returns the most recent parent node. + * Gets the current marker marker. + * @return object */ - getCurrentParentNode: () => parentMarkers.length ? parentMarkers[parentMarkers.length - 1] : null, - - /** - * Push a new parent node onto the stack and nest it with the - * next most recent parent node, or root if no other parent nodes. - */ - addParentNode: (marker) => { - let parentMarker = makeParentMarkerNode(marker); - (factory.getCurrentParentNode() || root).submarkers.push(parentMarker); - parentMarkers.push(parentMarker); + function getCurrentParentNode() { + return marker; }, /** - * Push this marker into the most recent parent node. + * Clears the current marker marker. */ - collapseMarker: (marker) => { - if (parentMarkers.length === 0) { - throw new Error("Cannot collapse marker with no parents."); - } - factory.getCurrentParentNode().submarkers.push(marker); + function clearParentNode() { + marker = null; } - }; - - return factory; + ]; } -exports.makeParentMarkerNode = makeParentMarkerNode; +exports.makeEmptyMarkerNode = makeEmptyMarkerNode; exports.collapseMarkersIntoNode = collapseMarkersIntoNode;
--- a/browser/devtools/performance/modules/markers.js +++ b/browser/devtools/performance/modules/markers.js @@ -1,15 +1,15 @@ /* 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 { L10N } = require("devtools/performance/global"); -const { Formatters, CollapseFunctions: collapse } = require("devtools/performance/marker-utils"); +const { Formatters, CollapseFunctions } = require("devtools/performance/marker-utils"); /** * A simple schema for mapping markers to the timeline UI. The keys correspond * to marker names, while the values are objects with the following format: * * - group: The row index in the timeline overview graph; multiple markers * can be added on the same row. @see <overview.js/buildGraphImage> * - label: The label used in the waterfall to identify the marker. Can be a @@ -24,23 +24,25 @@ const { Formatters, CollapseFunctions: c * entry in ./browser/themes/shared/devtools/performance.inc.css * https://developer.mozilla.org/en-US/docs/Tools/DevToolsColors * - collapseFunc: A function determining how markers are collapsed together. * Invoked with 3 arguments: the current parent marker, the * current marker and a method for peeking i markers ahead. If * nothing is returned, the marker is added as a standalone entry * in the waterfall. Otherwise, an object needs to be returned * with the following properties: - * - toParent: The marker to be made a new parent. Can use the current - * marker, becoming a parent itself, or make a new marker-esque - * object. - * - collapse: Whether or not this current marker should be nested within - * the current parent. - * - finalize: Whether or not the current parent should be finalized and popped - * off the stack. + * - toParent: The parent marker name (needs to be an entry in + * the `TIMELINE_BLUEPRINT` itself). + * - withData: An object containing some properties to staple + * on the parent marker. + * - forceNew: True if a new parent marker needs to be created + * even though there is one currently available + * with the same name. + * - forceEnd: True if the current parent marker is full after + * this collapse operation and should be finalized. * - fields: An optional array of marker properties you wish to display in the * marker details view. For example, a field in the array such as * { property: "aCauseName", label: "Cause" } would render a string * like `Cause: ${marker.aCauseName}` in the marker details view. * Each `field` item may take the following properties: * - property: The property that must exist on the marker to render, * and the value of the property will be displayed. * - label: The name of the property that should be displayed. @@ -54,64 +56,69 @@ const { Formatters, CollapseFunctions: c * Whenever this is changed, browser_timeline_waterfall-styles.js *must* be * updated as well. */ const TIMELINE_BLUEPRINT = { /* Group 0 - Reflow and Rendering pipeline */ "Styles": { group: 0, colorName: "graphs-purple", - collapseFunc: collapse.child, + collapseFunc: CollapseFunctions.identical, label: L10N.getStr("timeline.label.styles2"), fields: Formatters.StylesFields, }, "Reflow": { group: 0, colorName: "graphs-purple", - collapseFunc: collapse.child, + collapseFunc: CollapseFunctions.identical, label: L10N.getStr("timeline.label.reflow2"), }, "Paint": { group: 0, colorName: "graphs-green", - collapseFunc: collapse.child, + collapseFunc: CollapseFunctions.identical, label: L10N.getStr("timeline.label.paint"), }, /* Group 1 - JS */ "DOMEvent": { group: 1, colorName: "graphs-yellow", - collapseFunc: collapse.parent, + collapseFunc: CollapseFunctions.DOMtoDOMJS, label: L10N.getStr("timeline.label.domevent"), fields: Formatters.DOMEventFields, }, "Javascript": { group: 1, colorName: "graphs-yellow", - collapseFunc: either(collapse.parent, collapse.child), + collapseFunc: either(CollapseFunctions.JStoDOMJS, CollapseFunctions.identical), label: Formatters.JSLabel, fields: Formatters.JSFields }, + "meta::DOMEvent+JS": { + colorName: "graphs-yellow", + label: Formatters.DOMJSLabel, + fields: Formatters.DOMJSFields, + }, "Parse HTML": { group: 1, colorName: "graphs-yellow", - collapseFunc: either(collapse.parent, collapse.child), + collapseFunc: CollapseFunctions.identical, label: L10N.getStr("timeline.label.parseHTML"), }, "Parse XML": { group: 1, colorName: "graphs-yellow", - collapseFunc: either(collapse.parent, collapse.child), + collapseFunc: CollapseFunctions.identical, label: L10N.getStr("timeline.label.parseXML"), }, "GarbageCollection": { group: 1, colorName: "graphs-red", - collapseFunc: either(collapse.parent, collapse.child), + collapseFunc: CollapseFunctions.adjacent, label: Formatters.GCLabel, fields: [ { property: "causeName", label: "Reason:" }, { property: "nonincrementalReason", label: "Non-incremental Reason:" } ], }, /* Group 2 - User Controlled */ @@ -122,17 +129,16 @@ const TIMELINE_BLUEPRINT = { fields: [{ property: "causeName", label: L10N.getStr("timeline.markerDetail.consoleTimerName") }], }, "TimeStamp": { group: 2, colorName: "graphs-blue", - collapseFunc: collapse.child, label: sublabelForProperty(L10N.getStr("timeline.label.timestamp"), "causeName"), fields: [{ property: "causeName", label: "Label:" }], }, };
--- a/browser/devtools/performance/test/browser.ini +++ b/browser/devtools/performance/test/browser.ini @@ -133,8 +133,9 @@ support-files = [browser_profiler_tree-view-10.js] [browser_timeline-blueprint.js] [browser_timeline-filters.js] [browser_timeline-waterfall-background.js] [browser_timeline-waterfall-generic.js] [browser_timeline-waterfall-rerender.js] [browser_timeline-waterfall-sidebar.js] skip-if = os == 'linux' # Bug 1161817 +[browser_waterfall-collapse.js]
new file mode 100644 --- /dev/null +++ b/browser/devtools/performance/test/browser_waterfall-collapse.js @@ -0,0 +1,392 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +/** + * Tests if the waterfall collapsing logic works properly. + */ + +function test() { + const WaterfallUtils = devtools.require("devtools/performance/waterfall-utils"); + + let rootMarkerNode = WaterfallUtils.makeEmptyMarkerNode("(root)"); + + WaterfallUtils.collapseMarkersIntoNode({ + markerNode: rootMarkerNode, + markersList: gTestMarkers + }); + + is(rootMarkerNode.toSource(), gExpectedOutput.toSource(), + "The markers didn't collapse properly."); + + finish(); +} + +const gTestMarkers = [ +// Test collapsing Style markers +{ + start: 1, + end: 2, + name: "Styles" +}, +{ + start: 3, + end: 4, + name: "Styles" +}, +// Test collapsing Reflow markers +{ + start: 5, + end: 6, + name: "Reflow" +}, +{ + start: 7, + end: 8, + name: "Reflow" +}, +// Test collapsing Paint markers +{ + start: 9, + end: 10, + name: "Paint" +}, { + start: 11, + end: 12, + name: "Paint" +}, +// Test standalone DOMEvent markers followed by a different marker +{ + start: 13, + end: 14, + name: "DOMEvent", + eventPhase: 1, + type: "foo1" +}, +{ + start: 15, + end: 16, + name: "TimeStamp" +}, +// Test a DOMEvent marker followed by a Javascript marker. +{ + start: 17, + end: 18, + name: "DOMEvent", + eventPhase: 2, + type: "foo2" +}, { + start: 19, + end: 20, + name: "Javascript", + stack: 1, + endStack: 2 +}, +// Test another DOMEvent marker followed by a Javascript marker. +{ + start: 21, + end: 22, + name: "DOMEvent", + eventPhase: 3, + type: "foo3" +}, { + start: 23, + end: 24, + name: "Javascript", + stack: 3, + endStack: 4 +}, +// Test a DOMEvent marker followed by multiple Javascript markers. +{ + start: 25, + end: 26, + name: "DOMEvent", + eventPhase: 4, + type: "foo4" +}, { + start: 27, + end: 28, + name: "Javascript", + stack: 5, + endStack: 6 +}, { + start: 29, + end: 30, + name: "Javascript", + stack: 7, + endStack: 8 +}, { + start: 31, + end: 32, + name: "Javascript", + stack: 9, + endStack: 10 +}, +// Test multiple DOMEvent markers followed by multiple Javascript markers. +{ + start: 33, + end: 34, + name: "DOMEvent", + eventPhase: 5, + type: "foo5" +}, { + start: 35, + end: 36, + name: "DOMEvent", + eventPhase: 6, + type: "foo6" +}, { + start: 37, + end: 38, + name: "DOMEvent", + eventPhase: 7, + type: "foo6" +}, { + start: 39, + end: 40, + name: "Javascript", + stack: 11, + endStack: 12 +}, { + start: 41, + end: 42, + name: "Javascript", + stack: 13, + endStack: 14 +}, { + start: 43, + end: 44, + name: "Javascript", + stack: 15, + endStack: 16 +}, +// Test a lonely marker at the end. +{ + start: 45, + end: 46, + name: "GarbageCollection" +} +]; + +const gExpectedOutput = { + name: "(root)", + uid: (void 0), + start: (void 0), + end: (void 0), + submarkers: [{ + name: "Styles", + uid: 2, + start: 1, + end: 4, + submarkers: [{ + start: 1, + end: 2, + name: "Styles", + uid: 1 + }, { + start: 3, + end: 4, + name: "Styles", + uid: 3 + }] + }, { + name: "Reflow", + uid: 6, + start: 5, + end: 8, + submarkers: [{ + start: 5, + end: 6, + name: "Reflow", + uid: 5 + }, { + start: 7, + end: 8, + name: "Reflow", + uid: 7 + }] + }, { + name: "Paint", + uid: 10, + start: 9, + end: 12, + submarkers: [{ + start: 9, + end: 10, + name: "Paint", + uid: 9 + }, { + start: 11, + end: 12, + name: "Paint", + uid: 11 + }] + }, { + start: 13, + end: 14, + name: "DOMEvent", + eventPhase: 1, + type: "foo1", + uid: 13 + }, { + start: 15, + end: 16, + name: "TimeStamp", + uid: 14 + }, { + name: "meta::DOMEvent+JS", + uid: 16, + start: 17, + end: 20, + submarkers: [{ + start: 17, + end: 18, + name: "DOMEvent", + eventPhase: 2, + type: "foo2", + uid: 15 + }, { + start: 19, + end: 20, + name: "Javascript", + stack: 1, + endStack: 2, + uid: 17 + }], + type: "foo2", + eventPhase: 2, + stack: 1, + endStack: 2 + }, { + name: "meta::DOMEvent+JS", + uid: 20, + start: 21, + end: 24, + submarkers: [{ + start: 21, + end: 22, + name: "DOMEvent", + eventPhase: 3, + type: "foo3", + uid: 19 + }, { + start: 23, + end: 24, + name: "Javascript", + stack: 3, + endStack: 4, + uid: 21 + }], + type: "foo3", + eventPhase: 3, + stack: 3, + endStack: 4 + }, { + name: "meta::DOMEvent+JS", + uid: 24, + start: 25, + end: 28, + submarkers: [{ + start: 25, + end: 26, + name: "DOMEvent", + eventPhase: 4, + type: "foo4", + uid: 23 + }, { + start: 27, + end: 28, + name: "Javascript", + stack: 5, + endStack: 6, + uid: 25 + }], + type: "foo4", + eventPhase: 4, + stack: 5, + endStack: 6 + }, { + name: "Javascript", + uid: 28, + start: 29, + end: 32, + submarkers: [{ + start: 29, + end: 30, + name: "Javascript", + stack: 7, + endStack: 8, + uid: 27 + }, { + start: 31, + end: 32, + name: "Javascript", + stack: 9, + endStack: 10, + uid: 29 + }] + }, { + start: 33, + end: 34, + name: "DOMEvent", + eventPhase: 5, + type: "foo5", + uid: 31 + }, { + start: 35, + end: 36, + name: "DOMEvent", + eventPhase: 6, + type: "foo6", + uid: 32 + }, { + name: "meta::DOMEvent+JS", + uid: 34, + start: 37, + end: 40, + submarkers: [{ + start: 37, + end: 38, + name: "DOMEvent", + eventPhase: 7, + type: "foo6", + uid: 33 + }, { + start: 39, + end: 40, + name: "Javascript", + stack: 11, + endStack: 12, + uid: 35 + }], + type: "foo6", + eventPhase: 7, + stack: 11, + endStack: 12 + }, { + name: "Javascript", + uid: 38, + start: 41, + end: 44, + submarkers: [{ + start: 41, + end: 42, + name: "Javascript", + stack: 13, + endStack: 14, + uid: 37 + }, { + start: 43, + end: 44, + name: "Javascript", + stack: 15, + endStack: 16, + uid: 39 + }] + }, { + start: 45, + end: 46, + name: "GarbageCollection", + uid: 41 + }] +}; +
deleted file mode 100644 --- a/browser/devtools/performance/test/unit/test_waterfall-utils-collapse-01.js +++ /dev/null @@ -1,67 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests if the waterfall collapsing logic works properly. - */ - -function test() { - const WaterfallUtils = devtools.require("devtools/performance/waterfall-utils"); - - let rootMarkerNode = WaterfallUtils.makeParentMarkerNode({ name: "(root)" }); - - WaterfallUtils.collapseMarkersIntoNode({ - markerNode: rootMarkerNode, - markersList: gTestMarkers - }); - - function compare (marker, expected) { - for (let prop in expected) { - if (prop === "submarkers") { - for (let i = 0; i < expected.submarkers.length; i++) { - compare(marker.submarkers[i], expected.submarkers[i]); - } - } else if (prop !== "uid") { - is(marker[prop], expected[prop], `${expected.name} matches ${prop}`); - } - } - } - - compare(rootMarkerNode, gExpectedOutput); - finish(); -} - -const gTestMarkers = [ - { start: 1, end: 18, name: "DOMEvent" }, - // Test that JS markers can fold in DOM events and have marker children - { start: 2, end: 16, name: "Javascript" }, - // Test all these markers can be children - { start: 3, end: 4, name: "Paint" }, - { start: 5, end: 6, name: "Reflow" }, - { start: 7, end: 8, name: "Styles" }, - { start: 9, end: 9, name: "TimeStamp" }, - { start: 10, end: 11, name: "Parse HTML" }, - { start: 12, end: 13, name: "Parse XML" }, - { start: 14, end: 15, name: "GarbageCollection" }, - // Test that JS markers can be parents without being a child of DOM events - { start: 25, end: 30, name: "JavaScript" }, - { start: 26, end: 27, name: "Paint" }, -]; - -const gExpectedOutput = { - name: "(root)", submarkers: [ - { start: 1, end: 18, name: "DOMEvent", submarkers: [ - { start: 2, end: 16, name: "Javascript", submarkers: [ - { start: 3, end: 4, name: "Paint" }, - { start: 5, end: 6, name: "Reflow" }, - { start: 7, end: 8, name: "Styles" }, - { start: 9, end: 9, name: "TimeStamp" }, - { start: 10, end: 11, name: "Parse HTML" }, - { start: 12, end: 13, name: "Parse XML" }, - { start: 14, end: 15, name: "GarbageCollection" }, - ]} - ]}, - { start: 25, end: 30, name: "JavaScript", submarkers: [ - { start: 26, end: 27, name: "Paint" }, - ]} -]};
deleted file mode 100644 --- a/browser/devtools/performance/test/unit/test_waterfall-utils-collapse-02.js +++ /dev/null @@ -1,78 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ - -/** - * Tests if the waterfall collapsing logic works properly for console.time/console.timeEnd - * markers, as they should ignore any sort of collapsing. - */ - -function test() { - const WaterfallUtils = devtools.require("devtools/performance/waterfall-utils"); - - let rootMarkerNode = WaterfallUtils.makeParentMarkerNode({ name: "(root)" }); - - WaterfallUtils.collapseMarkersIntoNode({ - markerNode: rootMarkerNode, - markersList: gTestMarkers - }); - - function compare (marker, expected) { - for (let prop in expected) { - if (prop === "submarkers") { - for (let i = 0; i < expected.submarkers.length; i++) { - compare(marker.submarkers[i], expected.submarkers[i]); - } - } else if (prop !== "uid") { - is(marker[prop], expected[prop], `${expected.name} matches ${prop}`); - } - } - } - - compare(rootMarkerNode, gExpectedOutput); - finish(); -} - -const gTestMarkers = [ - { start: 2, end: 9, name: "Javascript" }, - { start: 3, end: 4, name: "Paint" }, - // Time range starting in nest, ending outside - { start: 5, end: 12, name: "ConsoleTime", causeName: "1" }, - - // Time range starting outside of nest, ending inside - { start: 15, end: 21, name: "ConsoleTime", causeName: "2" }, - { start: 18, end: 22, name: "Javascript" }, - { start: 19, end: 20, name: "Paint" }, - - // Time range completely eclipsing nest - { start: 30, end: 40, name: "ConsoleTime", causeName: "3" }, - { start: 34, end: 39, name: "Javascript" }, - { start: 35, end: 36, name: "Paint" }, - - // Time range completely eclipsed by nest - { start: 50, end: 60, name: "Javascript" }, - { start: 54, end: 59, name: "ConsoleTime", causeName: "4" }, - { start: 56, end: 57, name: "Paint" }, -]; - -const gExpectedOutput = { - name: "(root)", submarkers: [ - { start: 2, end: 9, name: "Javascript", submarkers: [ - { start: 3, end: 4, name: "Paint" } - ]}, - { start: 5, end: 12, name: "ConsoleTime", causeName: "1" }, - - { start: 15, end: 21, name: "ConsoleTime", causeName: "2" }, - { start: 18, end: 22, name: "Javascript", submarkers: [ - { start: 19, end: 20, name: "Paint" } - ]}, - - { start: 30, end: 40, name: "ConsoleTime", causeName: "3" }, - { start: 34, end: 39, name: "Javascript", submarkers: [ - { start: 35, end: 36, name: "Paint" }, - ]}, - - { start: 50, end: 60, name: "Javascript", submarkers: [ - { start: 56, end: 57, name: "Paint" }, - ]}, - { start: 54, end: 59, name: "ConsoleTime", causeName: "4" }, -]};
--- a/browser/devtools/performance/test/unit/xpcshell.ini +++ b/browser/devtools/performance/test/unit/xpcshell.ini @@ -12,10 +12,8 @@ skip-if = toolkit == 'android' || toolki [test_tree-model-02.js] [test_tree-model-03.js] [test_tree-model-04.js] [test_tree-model-05.js] [test_tree-model-06.js] [test_tree-model-07.js] [test_tree-model-08.js] [test_tree-model-09.js] -[test_waterfall-utils-collapse-01.js] -[test_waterfall-utils-collapse-02.js]
--- a/browser/devtools/performance/views/details-waterfall.js +++ b/browser/devtools/performance/views/details-waterfall.js @@ -85,17 +85,17 @@ let WaterfallView = Heritage.extend(Deta */ _onMarkerSelected: function (event, marker) { let recording = PerformanceController.getCurrentRecording(); let frames = recording.getFrames(); if (event === "selected") { this.details.render({ toolbox: gToolbox, marker, frames }); this.details.hidden = false; - this._lastSelected = marker; + this._lastSelected = marker.uid; } if (event === "unselected") { this.details.empty(); } }, /** * Called when the marker details view is resized. @@ -127,17 +127,17 @@ let WaterfallView = Heritage.extend(Deta * populate the waterfall tree. */ _prepareWaterfallTree: function(markers) { let cached = this._cache.get(markers); if (cached) { return cached; } - let rootMarkerNode = WaterfallUtils.makeParentMarkerNode({ name: "(root)" }); + let rootMarkerNode = WaterfallUtils.makeEmptyMarkerNode("(root)"); WaterfallUtils.collapseMarkersIntoNode({ markerNode: rootMarkerNode, markersList: markers }); this._cache.set(markers, rootMarkerNode); return rootMarkerNode; @@ -170,17 +170,17 @@ let WaterfallView = Heritage.extend(Deta root.attachTo(this.breakdownContainer); this.headerContainer.innerHTML = ""; header.attachTo(this.headerContainer); // If an item was previously selected in this view, attempt to // re-select it by traversing the newly created tree. if (this._lastSelected) { - let item = root.find(i => i.marker === this._lastSelected); + let item = root.find(i => i.marker.uid == this._lastSelected); if (item) { item.focus(); } } }, toString: () => "[object WaterfallView]" });