diff --git a/devtools/client/performance/legacy/actors.js b/devtools/client/performance/legacy/actors.js deleted file mode 100644 index d2be318c46f5..000000000000 --- a/devtools/client/performance/legacy/actors.js +++ /dev/null @@ -1,263 +0,0 @@ -/* 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 { Task } = require("devtools/shared/task"); - -const EventEmitter = require("devtools/shared/event-emitter"); -const { Poller } = require("devtools/client/shared/poller"); - -const CompatUtils = require("devtools/client/performance/legacy/compatibility"); -const RecordingUtils = require("devtools/shared/performance/recording-utils"); -const { TimelineFront } = require("devtools/shared/fronts/timeline"); -const { ProfilerFront } = require("devtools/shared/fronts/profiler"); - -// How often do we check the status of the profiler's circular buffer in milliseconds. -const PROFILER_CHECK_TIMER = 5000; - -const TIMELINE_ACTOR_METHODS = [ - "start", "stop", -]; - -const PROFILER_ACTOR_METHODS = [ - "startProfiler", "getStartOptions", "stopProfiler", - "registerEventNotifications", "unregisterEventNotifications" -]; - -/** - * Constructor for a facade around an underlying ProfilerFront. - */ -function LegacyProfilerFront(target) { - this._target = target; - this._onProfilerEvent = this._onProfilerEvent.bind(this); - this._checkProfilerStatus = this._checkProfilerStatus.bind(this); - this._PROFILER_CHECK_TIMER = this._target.TEST_MOCK_PROFILER_CHECK_TIMER || - PROFILER_CHECK_TIMER; - - EventEmitter.decorate(this); -} - -LegacyProfilerFront.prototype = { - EVENTS: ["console-api-profiler", "profiler-stopped"], - - // Connects to the targets underlying real ProfilerFront. - connect: Task.async(function* () { - let target = this._target; - this._front = new ProfilerFront(target.client, target.form); - - // Fetch and store information about the Gecko Profiler and - // server profiler. - this.traits = {}; - this.traits.filterable = target.getTrait("profilerDataFilterable"); - - // Directly register to event notifications when connected - // to hook into `console.profile|profileEnd` calls. - yield this.registerEventNotifications({ events: this.EVENTS }); - target.client.addListener("eventNotification", this._onProfilerEvent); - }), - - /** - * Unregisters events for the underlying profiler actor. - */ - destroy: Task.async(function* () { - if (this._poller) { - yield this._poller.destroy(); - } - yield this.unregisterEventNotifications({ events: this.EVENTS }); - this._target.client.removeListener("eventNotification", this._onProfilerEvent); - yield this._front.destroy(); - }), - - /** - * Starts the profiler actor, if necessary. - * - * @option {number?} bufferSize - * @option {number?} sampleFrequency - */ - start: Task.async(function* (options = {}) { - // Check for poller status even if the profiler is already active -- - // profiler can be activated via `console.profile` or another source, like - // the Gecko Profiler. - if (!this._poller) { - this._poller = new Poller(this._checkProfilerStatus, this._PROFILER_CHECK_TIMER, - false); - } - if (!this._poller.isPolling()) { - this._poller.on(); - } - - // Start the profiler only if it wasn't already active. The built-in - // nsIPerformance module will be kept recording, because it's the same instance - // for all targets and interacts with the whole platform, so we don't want - // to affect other clients by stopping (or restarting) it. - let { - isActive, - currentTime, - position, - generation, - totalSize - } = yield this.getStatus(); - - if (isActive) { - return { startTime: currentTime, position, generation, totalSize }; - } - - // Translate options from the recording model into profiler-specific - // options for the nsIProfiler - let profilerOptions = { - entries: options.bufferSize, - interval: options.sampleFrequency - ? (1000 / (options.sampleFrequency * 1000)) - : void 0 - }; - - let startInfo = yield this.startProfiler(profilerOptions); - let startTime = 0; - if ("currentTime" in startInfo) { - startTime = startInfo.currentTime; - } - - return { startTime, position, generation, totalSize }; - }), - - /** - * Indicates the end of a recording -- does not actually stop the profiler - * (stopProfiler does that), but notes that we no longer need to poll - * for buffer status. - */ - stop: Task.async(function* () { - yield this._poller.off(); - }), - - /** - * Wrapper around `profiler.isActive()` to take profiler status data and emit. - */ - getStatus: Task.async(function* () { - let data = yield (CompatUtils.callFrontMethod("isActive").call(this)); - // If no data, the last poll for `isActive()` was wrapping up, and the target.client - // is now null, so we no longer have data, so just abort here. - if (!data) { - return undefined; - } - - // If TEST_PROFILER_FILTER_STATUS defined (via array of fields), filter - // out any field from isActive, used only in tests. Used to filter out - // buffer status fields to simulate older geckos. - if (this._target.TEST_PROFILER_FILTER_STATUS) { - data = Object.keys(data).reduce((acc, prop) => { - if (this._target.TEST_PROFILER_FILTER_STATUS.indexOf(prop) === -1) { - acc[prop] = data[prop]; - } - return acc; - }, {}); - } - - this.emit("profiler-status", data); - return data; - }), - - /** - * Returns profile data from now since `startTime`. - */ - getProfile: Task.async(function* (options) { - let profilerData = yield (CompatUtils.callFrontMethod("getProfile") - .call(this, options)); - // If the backend is not deduped, dedupe it ourselves, as rest of the code - // expects a deduped profile. - if (profilerData.profile.meta.version === 2) { - RecordingUtils.deflateProfile(profilerData.profile); - } - - // If the backend does not support filtering by start and endtime on - // platform (< Fx40), do it on the client (much slower). - if (!this.traits.filterable) { - RecordingUtils.filterSamples(profilerData.profile, options.startTime || 0); - } - - return profilerData; - }), - - /** - * Invoked whenever a registered event was emitted by the profiler actor. - * - * @param object response - * The data received from the backend. - */ - _onProfilerEvent: function (_, { topic, subject, details }) { - if (topic === "console-api-profiler") { - if (subject.action === "profile") { - this.emit("console-profile-start", details); - } else if (subject.action === "profileEnd") { - this.emit("console-profile-stop", details); - } - } else if (topic === "profiler-stopped") { - this.emit("profiler-stopped"); - } - }, - - _checkProfilerStatus: Task.async(function* () { - // Calling `getStatus()` will emit the "profiler-status" on its own - yield this.getStatus(); - }), - - toString: () => "[object LegacyProfilerFront]" -}; - -/** - * Constructor for a facade around an underlying TimelineFront. - */ -function LegacyTimelineFront(target) { - this._target = target; - EventEmitter.decorate(this); -} - -LegacyTimelineFront.prototype = { - EVENTS: ["markers", "frames", "ticks"], - - connect: Task.async(function* () { - let supported = yield CompatUtils.timelineActorSupported(this._target); - this._front = supported ? - new TimelineFront(this._target.client, this._target.form) : - new CompatUtils.MockTimelineFront(); - - this.IS_MOCK = !supported; - - // Binds underlying actor events and consolidates them to a `timeline-data` - // exposed event. - this.EVENTS.forEach(type => { - let handler = this[`_on${type}`] = this._onTimelineData.bind(this, type); - this._front.on(type, handler); - }); - }), - - /** - * Override actor's destroy, so we can unregister listeners before - * destroying the underlying actor. - */ - destroy: Task.async(function* () { - this.EVENTS.forEach(type => this._front.off(type, this[`_on${type}`])); - yield this._front.destroy(); - }), - - /** - * An aggregate of all events (markers, frames, ticks) and exposes - * to PerformanceActorsConnection as a single event. - */ - _onTimelineData: function (type, ...data) { - this.emit("timeline-data", type, ...data); - }, - - toString: () => "[object LegacyTimelineFront]" -}; - -// Bind all the methods that directly proxy to the actor -PROFILER_ACTOR_METHODS.forEach(m => { - LegacyProfilerFront.prototype[m] = CompatUtils.callFrontMethod(m); -}); -TIMELINE_ACTOR_METHODS.forEach(m => { - LegacyTimelineFront.prototype[m] = CompatUtils.callFrontMethod(m); -}); - -exports.LegacyProfilerFront = LegacyProfilerFront; -exports.LegacyTimelineFront = LegacyTimelineFront; diff --git a/devtools/client/performance/legacy/compatibility.js b/devtools/client/performance/legacy/compatibility.js deleted file mode 100644 index 0c67800d034f..000000000000 --- a/devtools/client/performance/legacy/compatibility.js +++ /dev/null @@ -1,66 +0,0 @@ -/* 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 EventEmitter = require("devtools/shared/event-emitter"); - -/** - * A dummy front decorated with the provided methods. - * - * @param array blueprint - * A list of [funcName, retVal] describing the class. - */ -function MockFront(blueprint) { - EventEmitter.decorate(this); - - for (let [funcName, retVal] of blueprint) { - this[funcName] = (x => typeof x === "function" ? x() : x).bind(this, retVal); - } -} - -function MockTimelineFront() { - MockFront.call(this, [ - ["destroy"], - ["start", 0], - ["stop", 0], - ]); -} - -/** - * Takes a TabTarget, and checks existence of a TimelineActor on - * the server, or if TEST_MOCK_TIMELINE_ACTOR is to be used. - * - * @param {TabTarget} target - * @return {Boolean} - */ -function timelineActorSupported(target) { - // This `target` property is used only in tests to test - // instances where the timeline actor is not available. - if (target.TEST_MOCK_TIMELINE_ACTOR) { - return false; - } - - return target.hasActor("timeline"); -} - -/** - * Returns a function to be used as a method on an "Front" in ./actors. - * Calls the underlying actor's method. - */ -function callFrontMethod(method) { - return function () { - // If there's no target or client on this actor facade, - // abort silently -- this occurs in tests when polling occurs - // after the test ends, when tests do not wait for toolbox destruction - // (which will destroy the actor facade, turning off the polling). - if (!this._target || !this._target.client) { - return undefined; - } - return this._front[method].apply(this._front, arguments); - }; -} - -exports.MockTimelineFront = MockTimelineFront; -exports.timelineActorSupported = timelineActorSupported; -exports.callFrontMethod = callFrontMethod; diff --git a/devtools/client/performance/legacy/front.js b/devtools/client/performance/legacy/front.js deleted file mode 100644 index 34fb166659a4..000000000000 --- a/devtools/client/performance/legacy/front.js +++ /dev/null @@ -1,484 +0,0 @@ -/* 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 { Task } = require("devtools/shared/task"); - -const Services = require("Services"); -const promise = require("promise"); -const { extend } = require("sdk/util/object"); - -const Actors = require("devtools/client/performance/legacy/actors"); -const { LegacyPerformanceRecording } = require("devtools/client/performance/legacy/recording"); -const { importRecording } = require("devtools/client/performance/legacy/recording"); -const { normalizePerformanceFeatures } = require("devtools/shared/performance/recording-utils"); -const flags = require("devtools/shared/flags"); -const { getDeviceFront } = require("devtools/shared/device/device"); -const { getSystemInfo } = require("devtools/shared/system"); -const events = require("sdk/event/core"); -const { EventTarget } = require("sdk/event/target"); -const { Class } = require("sdk/core/heritage"); - -/** - * A connection to underlying actors (profiler, framerate, etc.) - * shared by all tools in a target. - */ -const LegacyPerformanceFront = Class({ - extends: EventTarget, - - LEGACY_FRONT: true, - - traits: { - features: { - withMarkers: true, - withTicks: true, - withMemory: false, - withFrames: false, - withGCEvents: false, - withDocLoadingEvents: false, - withAllocations: false, - }, - }, - - initialize: function (target) { - let { form, client } = target; - this._target = target; - this._form = form; - this._client = client; - this._pendingConsoleRecordings = []; - this._sitesPullTimeout = 0; - this._recordings = []; - - this._pipeToFront = this._pipeToFront.bind(this); - this._onTimelineData = this._onTimelineData.bind(this); - this._onConsoleProfileStart = this._onConsoleProfileStart.bind(this); - this._onConsoleProfileStop = this._onConsoleProfileStop.bind(this); - this._onProfilerStatus = this._onProfilerStatus.bind(this); - this._onProfilerUnexpectedlyStopped = this._onProfilerUnexpectedlyStopped.bind(this); - }, - - /** - * Initializes a connection to the profiler and other miscellaneous actors. - * If in the process of opening, or already open, nothing happens. - * - * @return object - * A promise that is resolved once the connection is established. - */ - connect: Task.async(function* () { - if (this._connecting) { - return this._connecting.promise; - } - - // Create a promise that gets resolved upon connecting, so that - // other attempts to open the connection use the same resolution promise - this._connecting = promise.defer(); - - // Sets `this._profiler`, `this._timeline`. - // Only initialize the timeline fronts if the respective actors - // are available. Older Gecko versions don't have existing implementations, - // in which case all the methods we need can be easily mocked. - yield this._connectActors(); - yield this._registerListeners(); - - this._connecting.resolve(); - return this._connecting.promise; - }), - - /** - * Destroys this connection. - */ - destroy: Task.async(function* () { - if (this._connecting) { - yield this._connecting.promise; - } else { - return; - } - - yield this._unregisterListeners(); - yield this._disconnectActors(); - - this._connecting = null; - this._profiler = null; - this._timeline = null; - this._client = null; - this._form = null; - this._target = this._target; - }), - - /** - * Initializes fronts and connects to the underlying actors using the facades - * found in ./actors.js. - */ - _connectActors: Task.async(function* () { - this._profiler = new Actors.LegacyProfilerFront(this._target); - this._timeline = new Actors.LegacyTimelineFront(this._target); - - yield promise.all([ - this._profiler.connect(), - this._timeline.connect() - ]); - - // If mocked timeline, update the traits - this.traits.features.withMarkers = !this._timeline.IS_MOCK; - this.traits.features.withTicks = !this._timeline.IS_MOCK; - }), - - /** - * Registers listeners on events from the underlying - * actors, so the connection can handle them. - */ - _registerListeners: function () { - this._timeline.on("timeline-data", this._onTimelineData); - this._profiler.on("console-profile-start", this._onConsoleProfileStart); - this._profiler.on("console-profile-stop", this._onConsoleProfileStop); - this._profiler.on("profiler-stopped", this._onProfilerUnexpectedlyStopped); - this._profiler.on("profiler-status", this._onProfilerStatus); - }, - - /** - * Unregisters listeners on events on the underlying actors. - */ - _unregisterListeners: function () { - this._timeline.off("timeline-data", this._onTimelineData); - this._profiler.off("console-profile-start", this._onConsoleProfileStart); - this._profiler.off("console-profile-stop", this._onConsoleProfileStop); - this._profiler.off("profiler-stopped", this._onProfilerUnexpectedlyStopped); - this._profiler.off("profiler-status", this._onProfilerStatus); - }, - - /** - * Closes the connections to non-profiler actors. - */ - _disconnectActors: Task.async(function* () { - yield promise.all([ - this._profiler.destroy(), - this._timeline.destroy(), - ]); - }), - - /** - * Invoked whenever `console.profile` is called. - * - * @param string profileLabel - * The provided string argument if available; undefined otherwise. - * @param number currentTime - * The time (in milliseconds) when the call was made, relative to when - * the nsIProfiler module was started. - */ - _onConsoleProfileStart: Task.async(function* (_, { profileLabel, - currentTime: startTime }) { - let recordings = this._recordings; - - // Abort if a profile with this label already exists. - if (recordings.find(e => e.getLabel() === profileLabel)) { - return; - } - - events.emit(this, "console-profile-start"); - - yield this.startRecording(extend({}, getLegacyPerformanceRecordingPrefs(), { - console: true, - label: profileLabel - })); - }), - - /** - * Invoked whenever `console.profileEnd` is called. - * - * @param string profileLabel - * The provided string argument if available; undefined otherwise. - * @param number currentTime - * The time (in milliseconds) when the call was made, relative to when - * the nsIProfiler module was started. - */ - _onConsoleProfileStop: Task.async(function* (_, data) { - // If no data, abort; can occur if profiler isn't running and we get a surprise - // call to console.profileEnd() - if (!data) { - return; - } - let { profileLabel } = data; - - let pending = this._recordings.filter(r => r.isConsole() && r.isRecording()); - if (pending.length === 0) { - return; - } - - let model; - // Try to find the corresponding `console.profile` call if - // a label was used in profileEnd(). If no matches, abort. - if (profileLabel) { - model = pending.find(e => e.getLabel() === profileLabel); - } else { - // If no label supplied, pop off the most recent pending console recording - model = pending[pending.length - 1]; - } - - // If `profileEnd()` was called with a label, and there are no matching - // sessions, abort. - if (!model) { - console.error( - "console.profileEnd() called with label that does not match a recording."); - return; - } - - yield this.stopRecording(model); - }), - - /** - * TODO handle bug 1144438 - */ - _onProfilerUnexpectedlyStopped: function () { - console.error("Profiler unexpectedly stopped.", arguments); - }, - - /** - * Called whenever there is timeline data of any of the following types: - * - markers - * - frames - * - ticks - * - * Populate our internal store of recordings for all currently recording sessions. - */ - _onTimelineData: function (_, ...data) { - this._recordings.forEach(e => e._addTimelineData.apply(e, data)); - events.emit(this, "timeline-data", ...data); - }, - - /** - * Called whenever the underlying profiler polls its current status. - */ - _onProfilerStatus: function (_, data) { - // If no data emitted (whether from an older actor being destroyed - // from a previous test, or the server does not support it), just ignore. - if (!data || data.position === void 0) { - return; - } - - this._currentBufferStatus = data; - events.emit(this, "profiler-status", data); - }, - - /** - * Begins a recording session - * - * @param object options - * An options object to pass to the actors. Supported properties are - * `withTicks`, `withMemory` and `withAllocations`, `probability`, and - * `maxLogLength`. - * @return object - * A promise that is resolved once recording has started. - */ - startRecording: Task.async(function* (options = {}) { - let model = new LegacyPerformanceRecording( - normalizePerformanceFeatures(options, this.traits.features)); - - // All actors are started asynchronously over the remote debugging protocol. - // Get the corresponding start times from each one of them. - // The timeline actors are target-dependent, so start those as well, - // even though these are mocked in older Geckos (FF < 35) - let profilerStart = this._profiler.start(options); - let timelineStart = this._timeline.start(options); - - let { startTime, position, generation, totalSize } = yield profilerStart; - let timelineStartTime = yield timelineStart; - - let data = { - profilerStartTime: startTime, timelineStartTime, - generation, position, totalSize - }; - - // Signify to the model that the recording has started, - // populate with data and store the recording model here. - model._populate(data); - this._recordings.push(model); - - events.emit(this, "recording-started", model); - return model; - }), - - /** - * Manually ends the recording session for the corresponding LegacyPerformanceRecording. - * - * @param LegacyPerformanceRecording model - * The corresponding LegacyPerformanceRecording that belongs to the recording - * session wished to stop. - * @return LegacyPerformanceRecording - * Returns the same model, populated with the profiling data. - */ - stopRecording: Task.async(function* (model) { - // If model isn't in the LegacyPerformanceFront internal store, - // then do nothing. - if (this._recordings.indexOf(model) === -1) { - return undefined; - } - - // Flag the recording as no longer recording, so that `model.isRecording()` - // is false. Do this before we fetch all the data, and then subsequently - // the recording can be considered "completed". - let endTime = Date.now(); - model._onStoppingRecording(endTime); - events.emit(this, "recording-stopping", model); - - // Currently there are two ways profiles stop recording. Either manually in the - // performance tool, or via console.profileEnd. Once a recording is done, - // we want to deliver the model to the performance tool (either as a return - // from the LegacyPerformanceFront or via `console-profile-stop` event) and then - // remove it from the internal store. - // - // In the case where a console.profile is generated via the console (so the tools are - // open), we initialize the Performance tool so it can listen to those events. - this._recordings.splice(this._recordings.indexOf(model), 1); - - let config = model.getConfiguration(); - let startTime = model._getProfilerStartTime(); - let profilerData = yield this._profiler.getProfile({ startTime }); - let timelineEndTime = Date.now(); - - // Only if there are no more sessions recording do we stop - // the underlying timeline actors. If we're still recording, - // juse use Date.now() for the timeline end times, as those - // are only used in tests. - if (!this.isRecording()) { - // This doesn't stop the profiler, just turns off polling for - // events, and also turns off events on timeline actors. - yield this._profiler.stop(); - timelineEndTime = yield this._timeline.stop(config); - } - - let form = yield this._client.listTabs(); - let systemHost = yield getDeviceFront(this._client, form).getDescription(); - let systemClient = yield getSystemInfo(); - - // Set the results on the LegacyPerformanceRecording itself. - model._onStopRecording({ - // Data available only at the end of a recording. - profile: profilerData.profile, - - // End times for all the actors. - profilerEndTime: profilerData.currentTime, - timelineEndTime: timelineEndTime, - systemHost, - systemClient, - }); - - events.emit(this, "recording-stopped", model); - return model; - }), - - /** - * Creates a recording object when given a nsILocalFile. - * - * @param {nsILocalFile} file - * The file to import the data from. - * @return {Promise} - */ - importRecording: function (file) { - return importRecording(file); - }, - - /** - * Checks all currently stored recording models and returns a boolean - * if there is a session currently being recorded. - * - * @return Boolean - */ - isRecording: function () { - return this._recordings.some(recording => recording.isRecording()); - }, - - /** - * Pass in a PerformanceRecording and get a normalized value from 0 to 1 of how much - * of this recording's lifetime remains without being overwritten. - * - * @param {PerformanceRecording} recording - * @return {number?} - */ - getBufferUsageForRecording: function (recording) { - if (!recording.isRecording() || !this._currentBufferStatus) { - return null; - } - let { - position: currentPosition, - totalSize, - generation: currentGeneration - } = this._currentBufferStatus; - let { - position: origPosition, - generation: origGeneration - } = recording.getStartingBufferStatus(); - - let normalizedCurrent = (totalSize * (currentGeneration - origGeneration)) - + currentPosition; - let percent = (normalizedCurrent - origPosition) / totalSize; - return percent > 1 ? 1 : percent; - }, - - /** - * Returns the configurations set on underlying components, used in tests. - * Returns an object with `probability`, `maxLogLength` for allocations, and - * `entries` and `interval` for profiler. - * - * @return {object} - */ - getConfiguration: Task.async(function* () { - let profilerConfig = yield this._request("profiler", "getStartOptions"); - return profilerConfig; - }), - - /** - * An event from an underlying actor that we just want - * to pipe to the front itself. - */ - _pipeToFront: function (eventName, ...args) { - events.emit(this, eventName, ...args); - }, - - /** - * Helper method to interface with the underlying actors directly. - * Used only in tests. - */ - _request: function (actorName, method, ...args) { - if (!flags.testing) { - throw new Error("LegacyPerformanceFront._request may only be used in tests."); - } - let actor = this[`_${actorName}`]; - return actor[method].apply(actor, args); - }, - - /** - * Sets how often the "profiler-status" event should be emitted. - * Used in tests. - */ - setProfilerStatusInterval: function (n) { - if (this._profiler._poller) { - this._profiler._poller._wait = n; - } - this._profiler._PROFILER_CHECK_TIMER = n; - }, - - toString: () => "[object LegacyPerformanceFront]" -}); - -/** - * Creates an object of configurations based off of preferences for a - * LegacyPerformanceRecording. - */ -function getLegacyPerformanceRecordingPrefs() { - return { - withMarkers: true, - withMemory: Services.prefs.getBoolPref( - "devtools.performance.ui.enable-memory"), - withTicks: Services.prefs.getBoolPref( - "devtools.performance.ui.enable-framerate"), - withAllocations: Services.prefs.getBoolPref( - "devtools.performance.ui.enable-allocations"), - allocationsSampleProbability: +Services.prefs.getCharPref( - "devtools.performance.memory.sample-probability"), - allocationsMaxLogLength: Services.prefs.getIntPref( - "devtools.performance.memory.max-log-length") - }; -} - -exports.LegacyPerformanceFront = LegacyPerformanceFront; diff --git a/devtools/client/performance/legacy/moz.build b/devtools/client/performance/legacy/moz.build deleted file mode 100644 index 00eab217b4dd..000000000000 --- a/devtools/client/performance/legacy/moz.build +++ /dev/null @@ -1,12 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# 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/. - -DevToolsModules( - 'actors.js', - 'compatibility.js', - 'front.js', - 'recording.js', -) diff --git a/devtools/client/performance/legacy/recording.js b/devtools/client/performance/legacy/recording.js deleted file mode 100644 index 2ba14147117d..000000000000 --- a/devtools/client/performance/legacy/recording.js +++ /dev/null @@ -1,174 +0,0 @@ -/* 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 { Task } = require("devtools/shared/task"); - -const PerformanceIO = require("devtools/client/performance/modules/io"); -const RecordingUtils = require("devtools/shared/performance/recording-utils"); -const { PerformanceRecordingCommon } = require("devtools/shared/performance/recording-common"); -const { merge } = require("sdk/util/object"); - -/** - * Model for a wholistic profile, containing the duration, profiling data, - * frames data, timeline (marker, tick, memory) data, and methods to mark - * a recording as 'in progress' or 'finished'. - */ -const LegacyPerformanceRecording = function (options = {}) { - this._label = options.label || ""; - this._console = options.console || false; - - this._configuration = { - withMarkers: options.withMarkers || false, - withTicks: options.withTicks || false, - withMemory: options.withMemory || false, - withAllocations: options.withAllocations || false, - allocationsSampleProbability: options.allocationsSampleProbability || 0, - allocationsMaxLogLength: options.allocationsMaxLogLength || 0, - bufferSize: options.bufferSize || 0, - sampleFrequency: options.sampleFrequency || 1 - }; -}; - -LegacyPerformanceRecording.prototype = merge({ - _profilerStartTime: 0, - _timelineStartTime: 0, - _memoryStartTime: 0, - - /** - * Saves the current recording to a file. - * - * @param nsILocalFile file - * The file to stream the data into. - */ - exportRecording: Task.async(function* (file) { - let recordingData = this.getAllData(); - yield PerformanceIO.saveRecordingToFile(recordingData, file); - }), - - /** - * Sets up the instance with data from the PerformanceFront when - * starting a recording. Should only be called by PerformanceFront. - */ - _populate: function (info) { - // Times must come from the actor in order to be self-consistent. - // However, we also want to update the view with the elapsed time - // even when the actor is not generating data. To do this we get - // the local time and use it to compute a reasonable elapsed time. - this._localStartTime = Date.now(); - - this._profilerStartTime = info.profilerStartTime; - this._timelineStartTime = info.timelineStartTime; - this._memoryStartTime = info.memoryStartTime; - this._startingBufferStatus = { - position: info.position, - totalSize: info.totalSize, - generation: info.generation - }; - - this._recording = true; - - this._systemHost = {}; - this._systemClient = {}; - this._markers = []; - this._frames = []; - this._memory = []; - this._ticks = []; - this._allocations = { sites: [], timestamps: [], frames: [], sizes: [] }; - }, - - /** - * Called when the signal was sent to the front to no longer record more - * data, and begin fetching the data. There's some delay during fetching, - * even though the recording is stopped, the model is not yet completed until - * all the data is fetched. - */ - _onStoppingRecording: function (endTime) { - this._duration = endTime - this._localStartTime; - this._recording = false; - }, - - /** - * Sets results available from stopping a recording from PerformanceFront. - * Should only be called by PerformanceFront. - */ - _onStopRecording: Task.async(function* ({ profilerEndTime, profile, systemClient, - systemHost }) { - // Update the duration with the accurate profilerEndTime, so we don't have - // samples outside of the approximate duration set in `_onStoppingRecording`. - this._duration = profilerEndTime - this._profilerStartTime; - this._profile = profile; - this._completed = true; - - // We filter out all samples that fall out of current profile's range - // since the profiler is continuously running. Because of this, sample - // times are not guaranteed to have a zero epoch, so offset the - // timestamps. - RecordingUtils.offsetSampleTimes(this._profile, this._profilerStartTime); - - // Markers need to be sorted ascending by time, to be properly displayed - // in a waterfall view. - this._markers = this._markers.sort((a, b) => (a.start > b.start)); - - this._systemHost = systemHost; - this._systemClient = systemClient; - }), - - /** - * Gets the profile's start time. - * @return number - */ - _getProfilerStartTime: function () { - return this._profilerStartTime; - }, - - /** - * Fired whenever the PerformanceFront emits markers, memory or ticks. - */ - _addTimelineData: function (eventName, ...data) { - // If this model isn't currently recording, - // ignore the timeline data. - if (!this.isRecording()) { - return; - } - - let config = this.getConfiguration(); - - switch (eventName) { - // Accumulate timeline markers into an array. Furthermore, the timestamps - // do not have a zero epoch, so offset all of them by the start time. - case "markers": { - if (!config.withMarkers) { - break; - } - let [markers] = data; - RecordingUtils.offsetMarkerTimes(markers, this._timelineStartTime); - RecordingUtils.pushAll(this._markers, markers); - break; - } - // Accumulate stack frames into an array. - case "frames": { - if (!config.withMarkers) { - break; - } - let [, frames] = data; - RecordingUtils.pushAll(this._frames, frames); - break; - } - // Save the accumulated refresh driver ticks. - case "ticks": { - if (!config.withTicks) { - break; - } - let [, timestamps] = data; - this._ticks = timestamps; - break; - } - } - }, - - toString: () => "[object LegacyPerformanceRecording]" -}, PerformanceRecordingCommon); - -exports.LegacyPerformanceRecording = LegacyPerformanceRecording; diff --git a/devtools/client/performance/moz.build b/devtools/client/performance/moz.build index eb93360a7ffe..9b290a129ac1 100644 --- a/devtools/client/performance/moz.build +++ b/devtools/client/performance/moz.build @@ -5,7 +5,6 @@ DIRS += [ 'components', - 'legacy', 'modules', 'test', ] @@ -18,5 +17,5 @@ DevToolsModules( BROWSER_CHROME_MANIFESTS += ['test/browser.ini'] XPCSHELL_TESTS_MANIFESTS += ['test/unit/xpcshell.ini'] -with Files('**'): - BUG_COMPONENT = ('Firefox', 'Developer Tools: Performance Tools (Profiler/Timeline)') +with Files('**'): + BUG_COMPONENT = ('Firefox', 'Developer Tools: Performance Tools (Profiler/Timeline)') diff --git a/devtools/client/performance/performance-controller.js b/devtools/client/performance/performance-controller.js index 7d2295fa5419..b94c0c5c01bd 100644 --- a/devtools/client/performance/performance-controller.js +++ b/devtools/client/performance/performance-controller.js @@ -235,11 +235,6 @@ var PerformanceController = { * @return Promise:boolean */ canCurrentlyRecord: Task.async(function* () { - // If we're testing the legacy front, the performance actor will exist, - // with `canCurrentlyRecord` method; this ensures we test the legacy path. - if (gFront.LEGACY_FRONT) { - return true; - } let hasActor = yield gTarget.hasActor("performance"); if (!hasActor) { return true; diff --git a/devtools/shared/fronts/performance.js b/devtools/shared/fronts/performance.js index da5a9ffb0706..f6303709f91d 100644 --- a/devtools/shared/fronts/performance.js +++ b/devtools/shared/fronts/performance.js @@ -11,8 +11,6 @@ const { Task } = require("devtools/shared/task"); loader.lazyRequireGetter(this, "PerformanceIO", "devtools/client/performance/modules/io"); -loader.lazyRequireGetter(this, "LegacyPerformanceFront", - "devtools/client/performance/legacy/front", true); loader.lazyRequireGetter(this, "getSystemInfo", "devtools/shared/system", true); @@ -136,13 +134,5 @@ const PerformanceFront = FrontClassWithSpec(performanceSpec, { exports.PerformanceFront = PerformanceFront; exports.createPerformanceFront = function createPerformanceFront(target) { - // If we force legacy mode, or the server does not have a performance actor (< Fx42), - // use our LegacyPerformanceFront which will handle - // the communication over RDP to other underlying actors. - if (target.TEST_PERFORMANCE_LEGACY_FRONT || !target.form.performanceActor) { - return new LegacyPerformanceFront(target); - } - // If our server has a PerformanceActor implementation, set this - // up like a normal front. return new PerformanceFront(target.client, target.form); };