Bug 1077438 - Timeline actor should manage Framerate and Memory actors, r=jsantell

This commit is contained in:
Victor Porof 2014-10-12 10:50:56 +03:00
parent c525c66a3d
commit 08c1c31bc0
3 changed files with 124 additions and 3 deletions

View File

@ -23,9 +23,11 @@
const {Ci, Cu} = require("chrome");
const protocol = require("devtools/server/protocol");
const {method, Arg, RetVal} = protocol;
const {method, Arg, RetVal, Option} = protocol;
const events = require("sdk/event/core");
const {setTimeout, clearTimeout} = require("sdk/timers");
const {MemoryActor} = require("devtools/server/actors/memory");
const {FramerateActor} = require("devtools/server/actors/framerate");
// 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
@ -50,6 +52,26 @@ let TimelineActor = exports.TimelineActor = protocol.ActorClass({
"markers" : {
type: "markers",
markers: Arg(0, "array:json")
},
/**
* "memory" events emitted in tandem with "markers", if this was enabled
* when the recording started.
*/
"memory" : {
type: "memory",
delta: Arg(0, "number"),
measurement: Arg(1, "json")
},
/**
* "ticks" events (from the refresh driver) emitted in tandem with "markers",
* if this was enabled when the recording started.
*/
"ticks" : {
type: "ticks",
delta: Arg(0, "number"),
timestamps: Arg(1, "array:number")
}
},
@ -122,6 +144,12 @@ let TimelineActor = exports.TimelineActor = protocol.ActorClass({
if (markers.length > 0) {
events.emit(this, "markers", markers);
}
if (this._memoryActor) {
events.emit(this, "memory", Date.now(), this._memoryActor.measure());
}
if (this._framerateActor) {
events.emit(this, "ticks", Date.now(), this._framerateActor.getPendingTicks());
}
this._dataPullTimeout = setTimeout(() => {
this._pullTimelineData();
@ -143,7 +171,7 @@ let TimelineActor = exports.TimelineActor = protocol.ActorClass({
/**
* Start recording profile markers.
*/
start: method(function() {
start: method(function({ withMemory, withTicks }) {
if (this._isRecording) {
return;
}
@ -153,8 +181,22 @@ let TimelineActor = exports.TimelineActor = protocol.ActorClass({
docShell.recordProfileTimelineMarkers = true;
}
if (withMemory) {
this._memoryActor = new MemoryActor(this.conn, this.tabActor);
events.emit(this, "memory", Date.now(), this._memoryActor.measure());
}
if (withTicks) {
this._framerateActor = new FramerateActor(this.conn, this.tabActor);
this._framerateActor.startRecording();
}
this._pullTimelineData();
}, {}),
}, {
request: {
withMemory: Option(0, "boolean"),
withTicks: Option(0, "boolean")
}
}),
/**
* Stop recording profile markers.
@ -165,6 +207,14 @@ let TimelineActor = exports.TimelineActor = protocol.ActorClass({
}
this._isRecording = false;
if (this._memoryActor) {
this._memoryActor = null;
}
if (this._framerateActor) {
this._framerateActor.stopRecording();
this._framerateActor = null;
}
for (let docShell of this.docShells) {
docShell.recordProfileTimelineMarkers = false;
}

View File

@ -19,5 +19,7 @@ support-files =
[browser_storage_updates.js]
[browser_timeline.js]
skip-if = buildapp == 'mulet'
[browser_timeline_actors.js]
skip-if = buildapp == 'mulet'
[browser_timeline_iframes.js]
skip-if = buildapp == 'mulet'

View File

@ -0,0 +1,69 @@
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
// Test that the timeline can also record data from the memory and framerate
// actors, emitted as events in tadem with the markers.
const {TimelineFront} = require("devtools/server/actors/timeline");
let test = asyncTest(function*() {
let doc = yield addTab("data:text/html;charset=utf-8,mop");
initDebuggerServer();
let client = new DebuggerClient(DebuggerServer.connectPipe());
let form = yield connectDebuggerClient(client);
let front = TimelineFront(client, form);
info("Start timeline marker recording");
yield front.start({ withMemory: true, withTicks: true });
let updatedMemory = 0;
let updatedTicks = 0;
front.on("memory", (delta, measurement) => {
ok(delta > 0, "The delta should be a timestamp.");
ok(measurement, "The measurement should not be null.");
ok(measurement.total > 0, "There should be a 'total' value in the measurement.");
info("Received 'memory' event at " + delta + " with " + measurement.toSource());
updatedMemory++;
});
front.on("ticks", (delta, ticks) => {
ok(delta > 0, "The delta should be a timestamp.");
ok(ticks, "The ticks should not be null.");
info("Received 'ticks' event with " + ticks.toSource());
updatedTicks++;
});
ok((yield waitUntil(() => updatedMemory > 1)),
"Some memory measurements were emitted.");
ok((yield waitUntil(() => updatedTicks > 1)),
"Some refresh driver ticks were emitted.");
info("Stop timeline marker recording");
yield front.stop();
yield closeDebuggerClient(client);
gBrowser.removeCurrentTab();
});
/**
* Waits until a predicate returns true.
*
* @param function predicate
* Invoked once in a while until it returns true.
* @param number interval [optional]
* How often the predicate is invoked, in milliseconds.
*/
function waitUntil(predicate, interval = 10) {
if (predicate()) {
return promise.resolve(true);
}
let deferred = promise.defer();
setTimeout(function() {
waitUntil(predicate).then(() => deferred.resolve(true));
}, interval);
return deferred.promise;
}