Bug 1378856 - Stop using sdk/core/heritage in DevTools performance server; r=zer0
MozReview-Commit-ID: DCECaZzAEDU
--- a/devtools/server/performance/framerate.js
+++ b/devtools/server/performance/framerate.js
@@ -1,99 +1,102 @@
/* 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 { on, off } = require("devtools/shared/event-emitter");
-const { Class } = require("sdk/core/heritage");
/**
* A very simple utility for monitoring framerate. Takes a `tabActor`
* and monitors framerate over time. The actor wrapper around this
* can be found at devtools/server/actors/framerate.js
*/
-exports.Framerate = Class({
- initialize: function (tabActor) {
+class Framerate {
+ constructor(tabActor) {
this.tabActor = tabActor;
this._contentWin = tabActor.window;
this._onRefreshDriverTick = this._onRefreshDriverTick.bind(this);
this._onGlobalCreated = this._onGlobalCreated.bind(this);
+
on(this.tabActor, "window-ready", this._onGlobalCreated);
- },
- destroy: function (conn) {
+ }
+
+ destroy(conn) {
off(this.tabActor, "window-ready", this._onGlobalCreated);
this.stopRecording();
- },
+ }
/**
* Starts monitoring framerate, storing the frames per second.
*/
- startRecording: function () {
+ startRecording() {
if (this._recording) {
return;
}
this._recording = true;
this._ticks = [];
this._startTime = this.tabActor.docShell.now();
this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
- },
+ }
/**
* Stops monitoring framerate, returning the recorded values.
*/
- stopRecording: function (beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
+ stopRecording(beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
if (!this._recording) {
return [];
}
let ticks = this.getPendingTicks(beginAt, endAt);
this.cancelRecording();
return ticks;
- },
+ }
/**
* Stops monitoring framerate, without returning the recorded values.
*/
- cancelRecording: function () {
+ cancelRecording() {
this._contentWin.cancelAnimationFrame(this._rafID);
this._recording = false;
this._ticks = null;
this._rafID = -1;
- },
+ }
/**
* Returns whether this instance is currently recording.
*/
- isRecording: function () {
+ isRecording() {
return !!this._recording;
- },
+ }
/**
* Gets the refresh driver ticks recorded so far.
*/
- getPendingTicks: function (beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
+ getPendingTicks(beginAt = 0, endAt = Number.MAX_SAFE_INTEGER) {
if (!this._ticks) {
return [];
}
return this._ticks.filter(e => e >= beginAt && e <= endAt);
- },
+ }
/**
* Function invoked along with the refresh driver.
*/
- _onRefreshDriverTick: function () {
+ _onRefreshDriverTick() {
if (!this._recording) {
return;
}
this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
this._ticks.push(this.tabActor.docShell.now() - this._startTime);
- },
+ }
/**
* When the content window for the tab actor is created.
*/
- _onGlobalCreated: function (win) {
+ _onGlobalCreated(win) {
if (this._recording) {
this._contentWin.cancelAnimationFrame(this._rafID);
this._rafID = this._contentWin.requestAnimationFrame(this._onRefreshDriverTick);
}
}
-});
+}
+
+exports.Framerate = Framerate;
--- a/devtools/server/performance/memory.js
+++ b/devtools/server/performance/memory.js
@@ -1,18 +1,18 @@
/* 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 { Cc, Ci, Cu } = require("chrome");
const { reportException } = require("devtools/shared/DevToolsUtils");
-const { Class } = require("sdk/core/heritage");
const { expectState } = require("devtools/server/actors/common");
+
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
loader.lazyRequireGetter(this, "DeferredTask",
"resource://gre/modules/DeferredTask.jsm", true);
loader.lazyRequireGetter(this, "StackFrameCache",
"devtools/server/actors/utils/stack", true);
loader.lazyRequireGetter(this, "ThreadSafeChromeUtils");
loader.lazyRequireGetter(this, "HeapSnapshotFileUtils",
"devtools/shared/heapsnapshot/HeapSnapshotFileUtils");
@@ -26,37 +26,34 @@ loader.lazyRequireGetter(this, "ChildPro
* Using a tab-scoped actor with this instance will measure the memory footprint of its
* parent tab. Using a global-scoped actor instance however, will measure the memory
* footprint of the chrome window referenced by its root actor.
*
* To be consumed by actor's, like MemoryActor using this module to
* send information over RDP, and TimelineActor for using more light-weight
* utilities like GC events and measuring memory consumption.
*/
-exports.Memory = Class({
- extends: EventEmitter,
+function Memory(parent, frameCache = new StackFrameCache()) {
+ EventEmitter.decorate(this);
- /**
- * Requires a root actor and a StackFrameCache.
- */
- initialize: function (parent, frameCache = new StackFrameCache()) {
- this.parent = parent;
- this._mgr = Cc["@mozilla.org/memory-reporter-manager;1"]
- .getService(Ci.nsIMemoryReporterManager);
- this.state = "detached";
- this._dbg = null;
- this._frameCache = frameCache;
+ this.parent = parent;
+ this._mgr = Cc["@mozilla.org/memory-reporter-manager;1"]
+ .getService(Ci.nsIMemoryReporterManager);
+ this.state = "detached";
+ this._dbg = null;
+ this._frameCache = frameCache;
- this._onGarbageCollection = this._onGarbageCollection.bind(this);
- this._emitAllocations = this._emitAllocations.bind(this);
- this._onWindowReady = this._onWindowReady.bind(this);
+ this._onGarbageCollection = this._onGarbageCollection.bind(this);
+ this._emitAllocations = this._emitAllocations.bind(this);
+ this._onWindowReady = this._onWindowReady.bind(this);
- EventEmitter.on(this.parent, "window-ready", this._onWindowReady);
- },
+ EventEmitter.on(this.parent, "window-ready", this._onWindowReady);
+}
+Memory.prototype = {
destroy: function () {
EventEmitter.off(this.parent, "window-ready", this._onWindowReady);
this._mgr = null;
if (this.state === "attached") {
this.detach();
}
},
@@ -421,10 +418,11 @@ exports.Memory = Class({
/**
* Accesses the docshell to return the current process time.
*/
_getCurrentTime: function () {
return (this.parent.isRootActor ? this.parent.docShell :
this.parent.originalDocShell).now();
},
+};
-});
+exports.Memory = Memory;
--- a/devtools/server/performance/profiler.js
+++ b/devtools/server/performance/profiler.js
@@ -1,16 +1,16 @@
/* 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 { Cc, Ci, Cu } = require("chrome");
const Services = require("Services");
-const { Class } = require("sdk/core/heritage");
+
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
loader.lazyRequireGetter(this, "DevToolsUtils", "devtools/shared/DevToolsUtils");
loader.lazyRequireGetter(this, "DeferredTask", "resource://gre/modules/DeferredTask.jsm", true);
loader.lazyRequireGetter(this, "Task", "devtools/shared/task", true);
// Events piped from system observers to Profiler instances.
const PROFILER_SYSTEM_EVENTS = [
"console-api-profiler",
@@ -401,147 +401,148 @@ const ProfilerManager = (function () {
this._poller.arm();
}
};
})();
/**
* The profiler actor provides remote access to the built-in nsIProfiler module.
*/
-var Profiler = exports.Profiler = Class({
- extends: EventEmitter,
+class Profiler {
+ constructor() {
+ EventEmitter.decorate(this);
- initialize: function () {
this.subscribedEvents = new Set();
ProfilerManager.addInstance(this);
- },
+ }
- destroy: function () {
+ destroy() {
this.unregisterEventNotifications({ events: Array.from(this.subscribedEvents) });
this.subscribedEvents = null;
+
ProfilerManager.removeInstance(this);
- },
+ }
/**
* @see ProfilerManager.start
*/
- start: function (options) {
+ start(options) {
return ProfilerManager.start(options);
- },
+ }
/**
* @see ProfilerManager.stop
*/
- stop: function () {
+ stop() {
return ProfilerManager.stop();
- },
+ }
/**
* @see ProfilerManager.getProfile
*/
- getProfile: function (request = {}) {
+ getProfile(request = {}) {
return ProfilerManager.getProfile(request);
- },
+ }
/**
* @see ProfilerManager.getFeatures
*/
- getFeatures: function () {
+ getFeatures() {
return ProfilerManager.getFeatures();
- },
+ }
/**
* @see ProfilerManager.getBufferInfo
*/
- getBufferInfo: function () {
+ getBufferInfo() {
return ProfilerManager.getBufferInfo();
- },
+ }
/**
* @see ProfilerManager.getStartOptions
*/
- getStartOptions: function () {
+ getStartOptions() {
return ProfilerManager.getStartOptions();
- },
+ }
/**
* @see ProfilerManager.isActive
*/
- isActive: function () {
+ isActive() {
return ProfilerManager.isActive();
- },
+ }
/**
* @see ProfilerManager.sharedLibraries
*/
- sharedLibraries: function () {
+ sharedLibraries() {
return ProfilerManager.sharedLibraries;
- },
+ }
/**
* @see ProfilerManager.setProfilerStatusInterval
*/
- setProfilerStatusInterval: function (interval) {
+ setProfilerStatusInterval(interval) {
return ProfilerManager.setProfilerStatusInterval(interval);
- },
+ }
/**
* Subscribes this instance to one of several events defined in
* an events array.
* - "console-api-profiler",
* - "profiler-started",
* - "profiler-stopped"
* - "profiler-status"
*
* @param {Array<string>} data.event
* @return {object}
*/
- registerEventNotifications: function (data = {}) {
+ registerEventNotifications(data = {}) {
let response = [];
(data.events || []).forEach(e => {
if (!this.subscribedEvents.has(e)) {
if (e === "profiler-status") {
ProfilerManager.subscribeToProfilerStatusEvents();
}
this.subscribedEvents.add(e);
response.push(e);
}
});
return { registered: response };
- },
+ }
/**
* Unsubscribes this instance to one of several events defined in
* an events array.
*
* @param {Array<string>} data.event
* @return {object}
*/
- unregisterEventNotifications: function (data = {}) {
+ unregisterEventNotifications(data = {}) {
let response = [];
(data.events || []).forEach(e => {
if (this.subscribedEvents.has(e)) {
if (e === "profiler-status") {
ProfilerManager.unsubscribeToProfilerStatusEvents();
}
this.subscribedEvents.delete(e);
response.push(e);
}
});
return { registered: response };
- },
-});
+ }
-/**
- * Checks whether or not the profiler module can currently run.
- * @return boolean
- */
-Profiler.canProfile = function () {
- return nsIProfilerModule.CanProfile();
-};
+ /**
+ * Checks whether or not the profiler module can currently run.
+ * @return boolean
+ */
+ static canProfile() {
+ return nsIProfilerModule.CanProfile();
+ }
+}
/**
* JSON.stringify callback used in Profiler.prototype.observe.
*/
function cycleBreaker(key, value) {
if (key == "wrappedJSObject") {
return undefined;
}
@@ -567,8 +568,10 @@ function sanitizeHandler(handler, identi
subject = JSON.parse(JSON.stringify(subject, cycleBreaker));
data = (data && !Cu.isXrayWrapper(data) && data.wrappedJSObject) || data;
data = JSON.parse(JSON.stringify(data, cycleBreaker));
// Pass in clean data to the underlying handler
return handler.call(this, subject, topic, data);
}, identifier);
}
+
+exports.Profiler = Profiler;
--- a/devtools/server/performance/recorder.js
+++ b/devtools/server/performance/recorder.js
@@ -42,30 +42,30 @@ const DRAIN_ALLOCATIONS_TIMEOUT = 2000;
/**
* A connection to underlying actors (profiler, memory, framerate, etc.)
* shared by all tools in a target.
*
* @param Target target
* The target owning this connection.
*/
-exports.PerformanceRecorder = Class({
- extends: EventEmitter,
+function PerformanceRecorder(conn, tabActor) {
+ EventEmitter.decorate(this);
- initialize: function (conn, tabActor) {
- this.conn = conn;
- this.tabActor = tabActor;
+ this.conn = conn;
+ this.tabActor = tabActor;
- this._pendingConsoleRecordings = [];
- this._recordings = [];
+ this._pendingConsoleRecordings = [];
+ this._recordings = [];
- this._onTimelineData = this._onTimelineData.bind(this);
- this._onProfilerEvent = this._onProfilerEvent.bind(this);
- },
+ this._onTimelineData = this._onTimelineData.bind(this);
+ this._onProfilerEvent = this._onProfilerEvent.bind(this);
+}
+PerformanceRecorder.prototype = {
/**
* Initializes a connection to the profiler and other miscellaneous actors.
* If in the process of opening, or already open, nothing happens.
*
* @param {Object} options.systemClient
* Metadata about the client's system to attach to the recording models.
*
* @return object
@@ -474,17 +474,17 @@ exports.PerformanceRecorder = Class({
if (this._memory.getState() === "attached") {
allocationSettings = this._memory.getAllocationsSettings();
}
return Object.assign({}, allocationSettings, this._profiler.getStartOptions());
},
toString: () => "[object PerformanceRecorder]"
-});
+};
/**
* Creates an object of configurations based off of
* preferences for a PerformanceRecording.
*/
function getPerformanceRecordingPrefs() {
return {
withMarkers: true,
@@ -493,8 +493,10 @@ function getPerformanceRecordingPrefs()
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.PerformanceRecorder = PerformanceRecorder;
--- a/devtools/server/performance/timeline.js
+++ b/devtools/server/performance/timeline.js
@@ -16,52 +16,50 @@
* timeline.stop()
* timeline.isRecording()
*
* When markers are available, an event is emitted:
* timeline.on("markers", function(markers) {...})
*/
const { Ci, Cu } = require("chrome");
-const { Class } = require("sdk/core/heritage");
+
// Be aggressive about lazy loading, as this will run on every
// toolbox startup
loader.lazyRequireGetter(this, "Task", "devtools/shared/task", true);
loader.lazyRequireGetter(this, "Memory", "devtools/server/performance/memory", true);
loader.lazyRequireGetter(this, "Framerate", "devtools/server/performance/framerate", true);
loader.lazyRequireGetter(this, "StackFrameCache", "devtools/server/actors/utils/stack", true);
loader.lazyRequireGetter(this, "EventEmitter", "devtools/shared/event-emitter");
// How often do we pull markers from the docShells, and therefore, how often do
// we send events to the front (knowing that when there are no markers in the
// docShell, no event is sent). In milliseconds.
const DEFAULT_TIMELINE_DATA_PULL_TIMEOUT = 200;
/**
* The timeline actor pops and forwards timeline markers registered in docshells.
*/
-exports.Timeline = Class({
- extends: EventEmitter,
- /**
- * Initializes this actor with the provided connection and tab actor.
- */
- initialize: function (tabActor) {
- this.tabActor = tabActor;
+function Timeline(tabActor) {
+ EventEmitter.decorate(this);
+
+ this.tabActor = tabActor;
- this._isRecording = false;
- this._stackFrames = null;
- this._memory = null;
- this._framerate = null;
+ this._isRecording = false;
+ this._stackFrames = null;
+ this._memory = null;
+ this._framerate = null;
- // Make sure to get markers from new windows as they become available
- this._onWindowReady = this._onWindowReady.bind(this);
- this._onGarbageCollection = this._onGarbageCollection.bind(this);
- EventEmitter.on(this.tabActor, "window-ready", this._onWindowReady);
- },
+ // Make sure to get markers from new windows as they become available
+ this._onWindowReady = this._onWindowReady.bind(this);
+ this._onGarbageCollection = this._onGarbageCollection.bind(this);
+ EventEmitter.on(this.tabActor, "window-ready", this._onWindowReady);
+}
+Timeline.prototype = {
/**
* Destroys this actor, stopping recording first.
*/
destroy: function () {
this.stop();
EventEmitter.off(this.tabActor, "window-ready", this._onWindowReady);
this.tabActor = null;
@@ -352,9 +350,11 @@ exports.Timeline = Class({
causeName: reason,
nonincrementalReason: nonincrementalReason,
cycle: gcCycleNumber,
start,
end,
};
}), endTime);
},
-});
+};
+
+exports.Timeline = Timeline;