зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1171488 - Attach host and client system data to recording profiles r=vp,mossop
This commit is contained in:
Родитель
5691e5b19a
Коммит
742c1b026f
|
@ -11,13 +11,27 @@ module.metadata = {
|
|||
const { Cc, Ci } = require('chrome');
|
||||
const system = require('../sdk/system');
|
||||
const runtime = require('../sdk/system/runtime');
|
||||
const oscpu = Cc["@mozilla.org/network/protocol;1?name=http"]
|
||||
.getService(Ci.nsIHttpProtocolHandler).oscpu;
|
||||
const hostname = Cc["@mozilla.org/network/dns-service;1"]
|
||||
.getService(Ci.nsIDNSService).myHostName;
|
||||
const { XPCOMUtils } = require("resource://gre/modules/XPCOMUtils.jsm");
|
||||
const isWindows = system.platform === 'win32';
|
||||
const endianness = ((new Uint32Array((new Uint8Array([1,2,3,4])).buffer))[0] === 0x04030201) ? 'LE' : 'BE';
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "oscpu", () => {
|
||||
try {
|
||||
return Cc["@mozilla.org/network/protocol;1?name=http"].getService(Ci.nsIHttpProtocolHandler).oscpu;
|
||||
} catch (e) {
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "hostname", () => {
|
||||
try {
|
||||
// On some platforms (Linux according to try), this service does not exist and fails.
|
||||
return Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService).myHostName;
|
||||
} catch (e) {
|
||||
return "";
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Returns a path to a temp directory
|
||||
*/
|
||||
|
|
|
@ -153,7 +153,9 @@ function convertLegacyData (legacyData) {
|
|||
withMarkers: false,
|
||||
withMemory: false,
|
||||
withAllocations: false
|
||||
}
|
||||
},
|
||||
systemHost: {},
|
||||
systemClient: {},
|
||||
};
|
||||
|
||||
return data;
|
||||
|
|
|
@ -21,6 +21,10 @@ loader.lazyRequireGetter(this, "normalizePerformanceFeatures",
|
|||
"devtools/toolkit/performance/utils", true);
|
||||
loader.lazyRequireGetter(this, "DevToolsUtils",
|
||||
"devtools/toolkit/DevToolsUtils");
|
||||
loader.lazyRequireGetter(this, "getDeviceFront",
|
||||
"devtools/toolkit/server/actors/device", true);
|
||||
loader.lazyRequireGetter(this, "getSystemInfo",
|
||||
"devtools/toolkit/shared/system", true);
|
||||
loader.lazyRequireGetter(this, "events",
|
||||
"sdk/event/core");
|
||||
loader.lazyRequireGetter(this, "EventTarget",
|
||||
|
@ -333,7 +337,7 @@ const LegacyPerformanceFront = Class({
|
|||
this._recordings.splice(this._recordings.indexOf(model), 1);
|
||||
|
||||
let config = model.getConfiguration();
|
||||
let startTime = model.getProfilerStartTime();
|
||||
let startTime = model._getProfilerStartTime();
|
||||
let profilerData = yield this._profiler.getProfile({ startTime });
|
||||
let timelineEndTime = Date.now();
|
||||
|
||||
|
@ -348,6 +352,13 @@ const LegacyPerformanceFront = Class({
|
|||
timelineEndTime = yield this._timeline.stop(config);
|
||||
}
|
||||
|
||||
let systemDeferred = promise.defer();
|
||||
this._client.listTabs(form => {
|
||||
systemDeferred.resolve(getDeviceFront(this._client, form).getDescription());
|
||||
});
|
||||
let systemHost = yield systemDeferred.promise;
|
||||
let systemClient = yield getSystemInfo();
|
||||
|
||||
// Set the results on the LegacyPerformanceRecording itself.
|
||||
model._onStopRecording({
|
||||
// Data available only at the end of a recording.
|
||||
|
@ -355,7 +366,9 @@ const LegacyPerformanceFront = Class({
|
|||
|
||||
// End times for all the actors.
|
||||
profilerEndTime: profilerData.currentTime,
|
||||
timelineEndTime: timelineEndTime
|
||||
timelineEndTime: timelineEndTime,
|
||||
systemHost,
|
||||
systemClient,
|
||||
});
|
||||
|
||||
events.emit(this, "recording-stopped", model);
|
||||
|
|
|
@ -10,6 +10,9 @@ loader.lazyRequireGetter(this, "PerformanceIO",
|
|||
"devtools/toolkit/performance/io");
|
||||
loader.lazyRequireGetter(this, "RecordingUtils",
|
||||
"devtools/toolkit/performance/utils");
|
||||
loader.lazyRequireGetter(this, "PerformanceRecordingCommon",
|
||||
"devtools/toolkit/performance/recording-common", true);
|
||||
loader.lazyRequireGetter(this, "merge", "sdk/util/object", true);
|
||||
|
||||
/**
|
||||
* Model for a wholistic profile, containing the duration, profiling data,
|
||||
|
@ -33,49 +36,10 @@ const LegacyPerformanceRecording = function (options={}) {
|
|||
};
|
||||
};
|
||||
|
||||
LegacyPerformanceRecording.prototype = {
|
||||
// Private fields, only needed when a recording is started or stopped.
|
||||
_console: false,
|
||||
_imported: false,
|
||||
_recording: false,
|
||||
_completed: false,
|
||||
LegacyPerformanceRecording.prototype = merge({
|
||||
_profilerStartTime: 0,
|
||||
_timelineStartTime: 0,
|
||||
_memoryStartTime: 0,
|
||||
_configuration: {},
|
||||
_startingBufferStatus: null,
|
||||
_bufferPercent: null,
|
||||
|
||||
// Serializable fields, necessary and sufficient for import and export.
|
||||
_label: "",
|
||||
_duration: 0,
|
||||
_markers: null,
|
||||
_frames: null,
|
||||
_memory: null,
|
||||
_ticks: null,
|
||||
_allocations: null,
|
||||
_profile: null,
|
||||
|
||||
/**
|
||||
* Loads a recording from a file.
|
||||
*
|
||||
* @param nsILocalFile file
|
||||
* The file to import the data form.
|
||||
*/
|
||||
importRecording: Task.async(function *(file) {
|
||||
let recordingData = yield PerformanceIO.loadRecordingFromFile(file);
|
||||
|
||||
this._imported = true;
|
||||
this._label = recordingData.label || "";
|
||||
this._duration = recordingData.duration;
|
||||
this._markers = recordingData.markers;
|
||||
this._frames = recordingData.frames;
|
||||
this._memory = recordingData.memory;
|
||||
this._ticks = recordingData.ticks;
|
||||
this._allocations = recordingData.allocations;
|
||||
this._profile = recordingData.profile;
|
||||
this._configuration = recordingData.configuration || {};
|
||||
}),
|
||||
|
||||
/**
|
||||
* Saves the current recording to a file.
|
||||
|
@ -107,11 +71,11 @@ LegacyPerformanceRecording.prototype = {
|
|||
totalSize: info.totalSize,
|
||||
generation: info.generation
|
||||
};
|
||||
// initialize the _bufferPercent if the server supports it.
|
||||
this._bufferPercent = info.position !== void 0 ? 0 : null;
|
||||
|
||||
this._recording = true;
|
||||
|
||||
this._systemHost = {};
|
||||
this._systemClient = {};
|
||||
this._markers = [];
|
||||
this._frames = [];
|
||||
this._memory = [];
|
||||
|
@ -134,7 +98,7 @@ LegacyPerformanceRecording.prototype = {
|
|||
* Sets results available from stopping a recording from PerformanceFront.
|
||||
* Should only be called by PerformanceFront.
|
||||
*/
|
||||
_onStopRecording: Task.async(function *({ profilerEndTime, profile }) {
|
||||
_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;
|
||||
|
@ -150,164 +114,19 @@ LegacyPerformanceRecording.prototype = {
|
|||
// 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 () {
|
||||
_getProfilerStartTime: function () {
|
||||
return this._profilerStartTime;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the profile's label, from `console.profile(LABEL)`.
|
||||
* @return string
|
||||
*/
|
||||
getLabel: function () {
|
||||
return this._label;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets duration of this recording, in milliseconds.
|
||||
* @return number
|
||||
*/
|
||||
getDuration: function () {
|
||||
// Compute an approximate ending time for the current recording if it is
|
||||
// still in progress. This is needed to ensure that the view updates even
|
||||
// when new data is not being generated.
|
||||
if (this._recording) {
|
||||
return Date.now() - this._localStartTime;
|
||||
} else {
|
||||
return this._duration;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns configuration object of specifying whether the recording
|
||||
* was started withTicks, withMemory and withAllocations, and other configurations.
|
||||
* @return object
|
||||
*/
|
||||
getConfiguration: function () {
|
||||
return this._configuration;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the accumulated markers in the current recording.
|
||||
* @return array
|
||||
*/
|
||||
getMarkers: function() {
|
||||
return this._markers;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the accumulated stack frames in the current recording.
|
||||
* @return array
|
||||
*/
|
||||
getFrames: function() {
|
||||
return this._frames;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the accumulated memory measurements in this recording.
|
||||
* @return array
|
||||
*/
|
||||
getMemory: function() {
|
||||
return this._memory;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the accumulated refresh driver ticks in this recording.
|
||||
* @return array
|
||||
*/
|
||||
getTicks: function() {
|
||||
return this._ticks;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the memory allocations data in this recording.
|
||||
* @return array
|
||||
*/
|
||||
getAllocations: function() {
|
||||
return this._allocations;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets the profiler data in this recording.
|
||||
* @return array
|
||||
*/
|
||||
getProfile: function() {
|
||||
return this._profile;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets all the data in this recording.
|
||||
*/
|
||||
getAllData: function() {
|
||||
let label = this.getLabel();
|
||||
let duration = this.getDuration();
|
||||
let markers = this.getMarkers();
|
||||
let frames = this.getFrames();
|
||||
let memory = this.getMemory();
|
||||
let ticks = this.getTicks();
|
||||
let allocations = this.getAllocations();
|
||||
let profile = this.getProfile();
|
||||
let configuration = this.getConfiguration();
|
||||
return { label, duration, markers, frames, memory, ticks, allocations, profile, configuration };
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating whether or not this recording model
|
||||
* was imported via file.
|
||||
*/
|
||||
isImported: function () {
|
||||
return this._imported;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating whether or not this recording model
|
||||
* was started via a `console.profile` call.
|
||||
*/
|
||||
isConsole: function () {
|
||||
return this._console;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating whether or not this recording model
|
||||
* has finished recording.
|
||||
* There is some delay in fetching data between when the recording stops, and
|
||||
* when the recording is considered completed once it has all the profiler and timeline data.
|
||||
*/
|
||||
isCompleted: function () {
|
||||
return this._completed || this.isImported();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating whether or not this recording model
|
||||
* is recording.
|
||||
* A model may no longer be recording, yet still not have the profiler data. In that
|
||||
* case, use `isCompleted()`.
|
||||
*/
|
||||
isRecording: function () {
|
||||
return this._recording;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns a boolean indicating if this recording is no longer recording, but
|
||||
* not yet completed.
|
||||
*/
|
||||
isFinalizing: function () {
|
||||
return !this.isRecording() && !this.isCompleted();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the position, generation and totalSize of the profiler
|
||||
* when this recording was started.
|
||||
*/
|
||||
getStartingBufferStatus: function () {
|
||||
return this._startingBufferStatus;
|
||||
},
|
||||
|
||||
/**
|
||||
* Fired whenever the PerformanceFront emits markers, memory or ticks.
|
||||
*/
|
||||
|
@ -348,6 +167,6 @@ LegacyPerformanceRecording.prototype = {
|
|||
},
|
||||
|
||||
toString: () => "[object LegacyPerformanceRecording]"
|
||||
};
|
||||
}, PerformanceRecordingCommon);
|
||||
|
||||
exports.LegacyPerformanceRecording = LegacyPerformanceRecording;
|
||||
|
|
|
@ -10,6 +10,7 @@ EXTRA_JS_MODULES.devtools.performance += [
|
|||
'io.js',
|
||||
'process-communication.js',
|
||||
'recorder.js',
|
||||
'recording-common.js',
|
||||
'utils.js',
|
||||
]
|
||||
|
||||
|
|
|
@ -25,13 +25,14 @@ loader.lazyRequireGetter(this, "Profiler",
|
|||
"devtools/toolkit/shared/profiler", true);
|
||||
loader.lazyRequireGetter(this, "PerformanceRecordingActor",
|
||||
"devtools/server/actors/performance-recording", true);
|
||||
|
||||
loader.lazyRequireGetter(this, "PerformanceRecordingFront",
|
||||
"devtools/server/actors/performance-recording", true);
|
||||
loader.lazyRequireGetter(this, "mapRecordingOptions",
|
||||
"devtools/toolkit/performance/utils", true);
|
||||
loader.lazyRequireGetter(this, "DevToolsUtils",
|
||||
"devtools/toolkit/DevToolsUtils");
|
||||
loader.lazyRequireGetter(this, "getSystemInfo",
|
||||
"devtools/toolkit/shared/system", true);
|
||||
|
||||
const PROFILER_EVENTS = [
|
||||
"console-api-profiler",
|
||||
|
@ -69,10 +70,13 @@ const PerformanceRecorder = exports.PerformanceRecorder = Class({
|
|||
* 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
|
||||
* A promise that is resolved once the connection is established.
|
||||
*/
|
||||
connect: function () {
|
||||
connect: function (options) {
|
||||
if (this._connected) {
|
||||
return;
|
||||
}
|
||||
|
@ -84,6 +88,8 @@ const PerformanceRecorder = exports.PerformanceRecorder = Class({
|
|||
this._connectComponents();
|
||||
this._registerListeners();
|
||||
|
||||
this._systemClient = options.systemClient;
|
||||
|
||||
this._connected = true;
|
||||
},
|
||||
|
||||
|
@ -341,6 +347,9 @@ const PerformanceRecorder = exports.PerformanceRecorder = Class({
|
|||
data.generation = profilerStartData.generation;
|
||||
data.totalSize = profilerStartData.totalSize;
|
||||
|
||||
data.systemClient = this._systemClient;
|
||||
data.systemHost = yield getSystemInfo();
|
||||
|
||||
let model = new PerformanceRecordingActor(this.conn, options, data);
|
||||
this._recordings.push(model);
|
||||
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/* 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";
|
||||
|
||||
/**
|
||||
* A mixin to be used for PerformanceRecordingActor, PerformanceRecordingFront,
|
||||
* and LegacyPerformanceRecording for helper methods to access data.
|
||||
*/
|
||||
|
||||
const PerformanceRecordingCommon = exports.PerformanceRecordingCommon = {
|
||||
// Private fields, only needed when a recording is started or stopped.
|
||||
_console: false,
|
||||
_imported: false,
|
||||
_recording: false,
|
||||
_completed: false,
|
||||
_configuration: {},
|
||||
_startingBufferStatus: null,
|
||||
_localStartTime: 0,
|
||||
|
||||
// Serializable fields, necessary and sufficient for import and export.
|
||||
_label: "",
|
||||
_duration: 0,
|
||||
_markers: null,
|
||||
_frames: null,
|
||||
_memory: null,
|
||||
_ticks: null,
|
||||
_allocations: null,
|
||||
_profile: null,
|
||||
_systemHost: null,
|
||||
_systemClient: null,
|
||||
|
||||
/**
|
||||
* Helper methods for returning the status of the recording.
|
||||
* These methods should be consistent on both the front and actor.
|
||||
*/
|
||||
isRecording: function () { return this._recording; },
|
||||
isCompleted: function () { return this._completed || this.isImported(); },
|
||||
isFinalizing: function () { return !this.isRecording() && !this.isCompleted(); },
|
||||
isConsole: function () { return this._console; },
|
||||
isImported: function () { return this._imported; },
|
||||
|
||||
/**
|
||||
* Helper methods for returning configuration for the recording.
|
||||
* These methods should be consistent on both the front and actor.
|
||||
*/
|
||||
getConfiguration: function () { return this._configuration; },
|
||||
getLabel: function () { return this._label; },
|
||||
|
||||
/**
|
||||
* Gets duration of this recording, in milliseconds.
|
||||
* @return number
|
||||
*/
|
||||
getDuration: function () {
|
||||
// Compute an approximate ending time for the current recording if it is
|
||||
// still in progress. This is needed to ensure that the view updates even
|
||||
// when new data is not being generated. If recording is completed, use
|
||||
// the duration from the profiler; if between recording and being finalized,
|
||||
// use the last estimated duration.
|
||||
if (this.isRecording()) {
|
||||
return this._estimatedDuration = Date.now() - this._localStartTime;
|
||||
} else {
|
||||
return this._duration || this._estimatedDuration || 0;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Helper methods for returning recording data.
|
||||
* These methods should be consistent on both the front and actor.
|
||||
*/
|
||||
getMarkers: function() { return this._markers; },
|
||||
getFrames: function() { return this._frames; },
|
||||
getMemory: function() { return this._memory; },
|
||||
getTicks: function() { return this._ticks; },
|
||||
getAllocations: function() { return this._allocations; },
|
||||
getProfile: function() { return this._profile; },
|
||||
getHostSystemInfo: function() { return this._systemHost; },
|
||||
getClientSystemInfo: function() { return this._systemClient; },
|
||||
getStartingBufferStatus: function() { return this._startingBufferStatus; },
|
||||
|
||||
getAllData: function () {
|
||||
let label = this.getLabel();
|
||||
let duration = this.getDuration();
|
||||
let markers = this.getMarkers();
|
||||
let frames = this.getFrames();
|
||||
let memory = this.getMemory();
|
||||
let ticks = this.getTicks();
|
||||
let allocations = this.getAllocations();
|
||||
let profile = this.getProfile();
|
||||
let configuration = this.getConfiguration();
|
||||
let systemHost = this.getHostSystemInfo();
|
||||
let systemClient = this.getClientSystemInfo();
|
||||
|
||||
return { label, duration, markers, frames, memory, ticks, allocations, profile, configuration, systemHost, systemClient };
|
||||
},
|
||||
};
|
|
@ -15,72 +15,8 @@ loader.lazyRequireGetter(this, "PerformanceIO",
|
|||
"devtools/toolkit/performance/io");
|
||||
loader.lazyRequireGetter(this, "RecordingUtils",
|
||||
"devtools/toolkit/performance/utils");
|
||||
|
||||
/**
|
||||
* A set of functions used by both the front and actor to access
|
||||
* internal properties.
|
||||
*/
|
||||
const PerformanceRecordingCommon = {
|
||||
// Private fields, only needed when a recording is started or stopped.
|
||||
_console: false,
|
||||
_imported: false,
|
||||
_recording: false,
|
||||
_completed: false,
|
||||
_configuration: {},
|
||||
_startingBufferStatus: null,
|
||||
_localStartTime: null,
|
||||
|
||||
// Serializable fields, necessary and sufficient for import and export.
|
||||
_label: "",
|
||||
_duration: 0,
|
||||
_markers: null,
|
||||
_frames: null,
|
||||
_memory: null,
|
||||
_ticks: null,
|
||||
_allocations: null,
|
||||
_profile: null,
|
||||
|
||||
/**
|
||||
* Helper methods for returning the status of the recording.
|
||||
* These methods should be consistent on both the front and actor.
|
||||
*/
|
||||
isRecording: function () { return this._recording; },
|
||||
isCompleted: function () { return this._completed || this.isImported(); },
|
||||
isFinalizing: function () { return !this.isRecording() && !this.isCompleted(); },
|
||||
isConsole: function () { return this._console; },
|
||||
isImported: function () { return this._imported; },
|
||||
|
||||
/**
|
||||
* Helper methods for returning configuration for the recording.
|
||||
* These methods should be consistent on both the front and actor.
|
||||
*/
|
||||
getConfiguration: function () { return this._configuration; },
|
||||
getLabel: function () { return this._label; },
|
||||
|
||||
/**
|
||||
* Helper methods for returning recording data.
|
||||
* These methods should be consistent on both the front and actor.
|
||||
*/
|
||||
getMarkers: function() { return this._markers; },
|
||||
getFrames: function() { return this._frames; },
|
||||
getMemory: function() { return this._memory; },
|
||||
getTicks: function() { return this._ticks; },
|
||||
getAllocations: function() { return this._allocations; },
|
||||
getProfile: function() { return this._profile; },
|
||||
|
||||
getAllData: function () {
|
||||
let label = this.getLabel();
|
||||
let duration = this.getDuration();
|
||||
let markers = this.getMarkers();
|
||||
let frames = this.getFrames();
|
||||
let memory = this.getMemory();
|
||||
let ticks = this.getTicks();
|
||||
let allocations = this.getAllocations();
|
||||
let profile = this.getProfile();
|
||||
let configuration = this.getConfiguration();
|
||||
return { label, duration, markers, frames, memory, ticks, allocations, profile, configuration };
|
||||
},
|
||||
};
|
||||
loader.lazyRequireGetter(this, "PerformanceRecordingCommon",
|
||||
"devtools/toolkit/performance/recording-common", true);
|
||||
|
||||
/**
|
||||
* This actor wraps the Performance module at toolkit/devtools/shared/performance.js
|
||||
|
@ -111,9 +47,12 @@ let PerformanceRecordingActor = exports.PerformanceRecordingActor = protocol.Act
|
|||
|
||||
// Only send profiler data once it exists and it has
|
||||
// not yet been sent
|
||||
if (this._profile && !this._sentProfilerData) {
|
||||
form.profile = this._profile;
|
||||
this._sentProfilerData = true;
|
||||
if (this._profile && !this._sentFinalizedData) {
|
||||
form.finalizedData = true;
|
||||
form.profile = this.getProfile();
|
||||
form.systemHost = this.getHostSystemInfo();
|
||||
form.systemClient = this.getClientSystemInfo();
|
||||
this._sentFinalizedData = true;
|
||||
}
|
||||
|
||||
return form;
|
||||
|
@ -164,6 +103,9 @@ let PerformanceRecordingActor = exports.PerformanceRecordingActor = protocol.Act
|
|||
this._memory = [];
|
||||
this._ticks = [];
|
||||
this._allocations = { sites: [], timestamps: [], frames: [], sizes: [] };
|
||||
|
||||
this._systemHost = meta.systemHost || {};
|
||||
this._systemClient = meta.systemClient || {};
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -233,8 +175,10 @@ let PerformanceRecordingFront = exports.PerformanceRecordingFront = protocol.Fro
|
|||
this._completed = form.completed;
|
||||
this._duration = form.duration;
|
||||
|
||||
if (form.profile) {
|
||||
if (form.finalizedData) {
|
||||
this._profile = form.profile;
|
||||
this._systemHost = form.systemHost;
|
||||
this._systemClient = form.systemClient;
|
||||
}
|
||||
|
||||
// Sort again on the client side if we're using realtime markers and the recording
|
||||
|
@ -270,33 +214,6 @@ let PerformanceRecordingFront = exports.PerformanceRecordingFront = protocol.Fro
|
|||
return PerformanceIO.saveRecordingToFile(recordingData, file);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the position, generation, and totalSize of the profiler
|
||||
* when this recording was started.
|
||||
*
|
||||
* @return {object}
|
||||
*/
|
||||
getStartingBufferStatus: function () {
|
||||
return this._form.startingBufferStatus;
|
||||
},
|
||||
|
||||
/**
|
||||
* Gets duration of this recording, in milliseconds.
|
||||
* @return number
|
||||
*/
|
||||
getDuration: function () {
|
||||
// Compute an approximate ending time for the current recording if it is
|
||||
// still in progress. This is needed to ensure that the view updates even
|
||||
// when new data is not being generated. If recording is completed, use
|
||||
// the duration from the profiler; if between recording and being finalized,
|
||||
// use the last estimated duration.
|
||||
if (this.isRecording()) {
|
||||
return this._estimatedDuration = Date.now() - this._localStartTime;
|
||||
} else {
|
||||
return this._duration || this._estimatedDuration || 0;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Fired whenever the PerformanceFront emits markers, memory or ticks.
|
||||
*/
|
||||
|
|
|
@ -22,6 +22,8 @@ loader.lazyRequireGetter(this, "normalizePerformanceFeatures",
|
|||
"devtools/toolkit/performance/utils", true);
|
||||
loader.lazyRequireGetter(this, "LegacyPerformanceFront",
|
||||
"devtools/toolkit/performance/legacy/front", true);
|
||||
loader.lazyRequireGetter(this, "getSystemInfo",
|
||||
"devtools/toolkit/shared/system", true);
|
||||
|
||||
const PIPE_TO_FRONT_EVENTS = new Set([
|
||||
"recording-started", "recording-stopping", "recording-stopped",
|
||||
|
@ -97,10 +99,13 @@ let PerformanceActor = exports.PerformanceActor = protocol.ActorClass({
|
|||
protocol.Actor.prototype.destroy.call(this);
|
||||
},
|
||||
|
||||
connect: method(function () {
|
||||
this.bridge.connect();
|
||||
return this.traits;
|
||||
}, { response: RetVal("json") }),
|
||||
connect: method(function (config) {
|
||||
this.bridge.connect({ systemClient: config.systemClient });
|
||||
return { traits: this.traits };
|
||||
}, {
|
||||
request: { options: Arg(0, "nullable:json") },
|
||||
response: RetVal("json")
|
||||
}),
|
||||
|
||||
startRecording: method(Task.async(function *(options={}) {
|
||||
let normalizedOptions = normalizePerformanceFeatures(options, this.traits.features);
|
||||
|
@ -182,9 +187,17 @@ const PerformanceFront = exports.PerformanceFront = protocol.FrontClass(Performa
|
|||
protocol.Front.prototype.destroy.call(this);
|
||||
},
|
||||
|
||||
connect: custom(function () {
|
||||
return this._connect().then(traits => this._traits = traits);
|
||||
}, {
|
||||
/**
|
||||
* Conenct to the server, and handle once-off tasks like storing traits
|
||||
* or system info.
|
||||
*/
|
||||
connect: custom(Task.async(function *() {
|
||||
let systemClient = yield getSystemInfo();
|
||||
let { traits } = yield this._connect({ systemClient });
|
||||
this._traits = traits;
|
||||
|
||||
return this._traits;
|
||||
}), {
|
||||
impl: "_connect"
|
||||
}),
|
||||
|
||||
|
@ -239,6 +252,8 @@ const PerformanceFront = exports.PerformanceFront = protocol.FrontClass(Performa
|
|||
model._allocations = recordingData.allocations;
|
||||
model._profile = recordingData.profile;
|
||||
model._configuration = recordingData.configuration || {};
|
||||
model._systemHost = recordingData.systemHost;
|
||||
model._systemClient = recordingData.systemClient;
|
||||
return model;
|
||||
});
|
||||
},
|
||||
|
|
|
@ -53,6 +53,8 @@ add_task(function*() {
|
|||
isEmptyArray(recording.getAllocations().timestamps, "allocations.timestamps");
|
||||
isEmptyArray(recording.getAllocations().frames, "allocations.frames");
|
||||
ok(recording.getProfile().threads[0].samples.data.length, "profile data has some samples");
|
||||
checkSystemInfo(recording, "Host");
|
||||
checkSystemInfo(recording, "Client");
|
||||
|
||||
yield front.destroy();
|
||||
yield closeDebuggerClient(target.client);
|
||||
|
@ -76,3 +78,10 @@ function getTab (url) {
|
|||
});
|
||||
});
|
||||
}
|
||||
|
||||
function checkSystemInfo (recording, type) {
|
||||
let data = recording[`get${type}SystemInfo`]();
|
||||
for (let field of ["appid", "apptype", "vendor", "name", "version"]) {
|
||||
ok(data[field], `get${type}SystemInfo() has ${field} property`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,6 +49,9 @@ add_task(function*() {
|
|||
ok(!rec.isRecording(), "on 'recording-stopped', model is still no longer recording");
|
||||
ok(rec.isCompleted(), "on 'recording-stopped', model is considered 'complete'");
|
||||
|
||||
checkSystemInfo(rec, "Host");
|
||||
checkSystemInfo(rec, "Client");
|
||||
|
||||
// Export and import a rec, and ensure it has the correct state.
|
||||
let file = FileUtils.getFile("TmpD", ["tmpprofile.json"]);
|
||||
file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, parseInt("666", 8));
|
||||
|
@ -60,7 +63,17 @@ add_task(function*() {
|
|||
ok(!importedModel.isRecording(), "All imported recordings should not be recording");
|
||||
ok(importedModel.isImported(), "All imported recordings should be considerd imported");
|
||||
|
||||
checkSystemInfo(importedModel, "Host");
|
||||
checkSystemInfo(importedModel, "Client");
|
||||
|
||||
yield front.destroy();
|
||||
yield closeDebuggerClient(client);
|
||||
gBrowser.removeCurrentTab();
|
||||
});
|
||||
|
||||
function checkSystemInfo (recording, type) {
|
||||
let data = recording[`get${type}SystemInfo`]();
|
||||
for (let field of ["appid", "apptype", "vendor", "name", "version"]) {
|
||||
ok(data[field], `get${type}SystemInfo() has ${field} property`);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ const { Task } = require("resource://gre/modules/Task.jsm");
|
|||
|
||||
loader.lazyRequireGetter(this, "Services");
|
||||
loader.lazyRequireGetter(this, "promise");
|
||||
loader.lazyRequireGetter(this, "OS", "resource://gre/modules/commonjs/node/os");
|
||||
loader.lazyRequireGetter(this, "OS", "resource://gre/modules/commonjs/node/os.js");
|
||||
loader.lazyRequireGetter(this, "DebuggerServer", "devtools/server/main", true);
|
||||
loader.lazyRequireGetter(this, "AppConstants",
|
||||
"resource://gre/modules/AppConstants.jsm", true);
|
||||
|
@ -164,18 +164,23 @@ function *getSystemInfo() {
|
|||
return info;
|
||||
}
|
||||
|
||||
function getProfileLocation() {
|
||||
let profd = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
|
||||
let profservice = Cc["@mozilla.org/toolkit/profile-service;1"].getService(Ci.nsIToolkitProfileService);
|
||||
var profiles = profservice.profiles;
|
||||
while (profiles.hasMoreElements()) {
|
||||
let profile = profiles.getNext().QueryInterface(Ci.nsIToolkitProfile);
|
||||
if (profile.rootDir.path == profd.path) {
|
||||
return profile = profile.name;
|
||||
function getProfileLocation () {
|
||||
// In child processes, we cannot access the profile location.
|
||||
try {
|
||||
let profd = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
|
||||
let profservice = Cc["@mozilla.org/toolkit/profile-service;1"].getService(Ci.nsIToolkitProfileService);
|
||||
var profiles = profservice.profiles;
|
||||
while (profiles.hasMoreElements()) {
|
||||
let profile = profiles.getNext().QueryInterface(Ci.nsIToolkitProfile);
|
||||
if (profile.rootDir.path == profd.path) {
|
||||
return profile = profile.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return profd.leafName;
|
||||
return profd.leafName;
|
||||
} catch (e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function getAppIniString(section, key) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче