parent
7a4a3c850f
commit
0949a4b045
|
@ -11,6 +11,7 @@ export {JsonFileReporter} from './src/reporter/json_file_reporter';
|
|||
export {SampleDescription} from './src/sample_description';
|
||||
export {PerflogMetric} from './src/metric/perflog_metric';
|
||||
export {ChromeDriverExtension} from './src/webdriver/chrome_driver_extension';
|
||||
export {FirefoxDriverExtension} from './src/webdriver/firefox_driver_extension';
|
||||
export {IOsDriverExtension} from './src/webdriver/ios_driver_extension';
|
||||
export {Runner} from './src/runner';
|
||||
export {Options} from './src/common_options';
|
||||
|
|
|
@ -1,11 +1,28 @@
|
|||
declare var exportFunction;
|
||||
declare var unsafeWindow;
|
||||
|
||||
exportFunction(function() { (<any>self).port.emit('startProfiler'); }, unsafeWindow,
|
||||
{defineAs: "startProfiler"});
|
||||
exportFunction(function() {
|
||||
var curTime = unsafeWindow.performance.now();
|
||||
(<any>self).port.emit('startProfiler', curTime);
|
||||
}, unsafeWindow, {defineAs: "startProfiler"});
|
||||
|
||||
exportFunction(function(filePath) { (<any>self).port.emit('stopAndRecord', filePath); },
|
||||
unsafeWindow, {defineAs: "stopAndRecord"});
|
||||
exportFunction(function() { (<any>self).port.emit('stopProfiler'); }, unsafeWindow,
|
||||
{defineAs: "stopProfiler"});
|
||||
|
||||
exportFunction(function(cb) {
|
||||
(<any>self).port.once('perfProfile', cb);
|
||||
(<any>self).port.emit('getProfile');
|
||||
}, unsafeWindow, {defineAs: "getProfile"});
|
||||
|
||||
exportFunction(function() { (<any>self).port.emit('forceGC'); }, unsafeWindow,
|
||||
{defineAs: "forceGC"});
|
||||
|
||||
exportFunction(function(name) {
|
||||
var curTime = unsafeWindow.performance.now();
|
||||
(<any>self).port.emit('markStart', name, curTime);
|
||||
}, unsafeWindow, {defineAs: "markStart"});
|
||||
|
||||
exportFunction(function(name) {
|
||||
var curTime = unsafeWindow.performance.now();
|
||||
(<any>self).port.emit('markEnd', name, curTime);
|
||||
}, unsafeWindow, {defineAs: "markEnd"});
|
||||
|
|
|
@ -1,52 +1,66 @@
|
|||
/// <reference path="../../../../angular2/typings/node/node.d.ts" />
|
||||
|
||||
var file = require('sdk/io/file');
|
||||
var {Cc, Ci, Cu} = require("chrome");
|
||||
var {Cc, Ci, Cu} = require('chrome');
|
||||
var os = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
|
||||
var ParserUtil = require('./parser_util');
|
||||
|
||||
class Profiler {
|
||||
private _profiler;
|
||||
constructor() { this._profiler = Cc["@mozilla.org/tools/profiler;1"].getService(Ci.nsIProfiler); }
|
||||
private _markerEvents: List<any>;
|
||||
private _profilerStartTime: number;
|
||||
|
||||
start(entries, interval, features) {
|
||||
constructor() { this._profiler = Cc['@mozilla.org/tools/profiler;1'].getService(Ci.nsIProfiler); }
|
||||
|
||||
start(entries, interval, features, timeStarted) {
|
||||
this._profiler.StartProfiler(entries, interval, features, features.length);
|
||||
this._profilerStartTime = timeStarted;
|
||||
this._markerEvents = [];
|
||||
}
|
||||
|
||||
stop() { this._profiler.StopProfiler(); }
|
||||
getProfileData() { return this._profiler.getProfileData(); }
|
||||
}
|
||||
|
||||
getProfilePerfEvents() {
|
||||
var profileData = this._profiler.getProfileData();
|
||||
var perfEvents = ParserUtil.convertPerfProfileToEvents(profileData);
|
||||
perfEvents = this._mergeMarkerEvents(perfEvents);
|
||||
perfEvents.sort(function(event1, event2) { return event1.ts - event2.ts; }); // Sort by ts
|
||||
return perfEvents;
|
||||
}
|
||||
|
||||
function saveToFile(savePath: string, body: string) {
|
||||
var textWriter = file.open(savePath, 'w');
|
||||
textWriter.write(body);
|
||||
textWriter.close();
|
||||
_mergeMarkerEvents(perfEvents: List<any>): List<any> {
|
||||
this._markerEvents.forEach(function(markerEvent) { perfEvents.push(markerEvent); });
|
||||
return perfEvents;
|
||||
}
|
||||
|
||||
addStartEvent(name: string, timeStarted: number) {
|
||||
this._markerEvents.push({ph: 'b', ts: timeStarted - this._profilerStartTime, name: name});
|
||||
}
|
||||
|
||||
addEndEvent(name: string, timeEnded: number) {
|
||||
this._markerEvents.push({ph: 'e', ts: timeEnded - this._profilerStartTime, name: name});
|
||||
}
|
||||
}
|
||||
|
||||
function forceGC() {
|
||||
Cu.forceGC();
|
||||
var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
|
||||
os.notifyObservers(null, "child-gc-request", null);
|
||||
}
|
||||
os.notifyObservers(null, 'child-gc-request', null);
|
||||
};
|
||||
|
||||
var mod = require('sdk/page-mod');
|
||||
var data = require('sdk/self').data;
|
||||
var profiler = new Profiler();
|
||||
function startProfiler() {
|
||||
profiler.start(/* = profiler memory */ 10000000, 1, ['leaf', 'js', "stackwalk", 'gc']);
|
||||
};
|
||||
function stopAndRecord(filePath) {
|
||||
var profileData = profiler.getProfileData();
|
||||
profiler.stop();
|
||||
saveToFile(filePath, JSON.stringify(profileData, null, 2));
|
||||
};
|
||||
|
||||
|
||||
var mod = require("sdk/page-mod");
|
||||
var data = require("sdk/self").data;
|
||||
mod.PageMod({
|
||||
include: ['*'],
|
||||
contentScriptFile: data.url("installed_script.js"),
|
||||
contentScriptFile: data.url('installed_script.js'),
|
||||
onAttach: worker => {
|
||||
worker.port.on('startProfiler', () => startProfiler());
|
||||
worker.port.on('stopAndRecord', filePath => stopAndRecord(filePath));
|
||||
worker.port.on('forceGC', () => forceGC());
|
||||
worker.port.on('startProfiler',
|
||||
(timeStarted) => profiler.start(/* = profiler memory */ 1000000, 1,
|
||||
['leaf', 'js', 'stackwalk', 'gc'], timeStarted));
|
||||
worker.port.on('stopProfiler', () => profiler.stop());
|
||||
worker.port.on('getProfile',
|
||||
() => worker.port.emit('perfProfile', profiler.getProfilePerfEvents()));
|
||||
worker.port.on('forceGC', forceGC);
|
||||
worker.port.on('markStart', (name, timeStarted) => profiler.addStartEvent(name, timeStarted));
|
||||
worker.port.on('markEnd', (name, timeEnded) => profiler.addEndEvent(name, timeEnded));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
library benchpress.src.firefox_extension.lib.parser_util;
|
||||
//no dart implementation
|
|
@ -0,0 +1,84 @@
|
|||
/// <reference path="../../../../angular2/typings/node/node.d.ts" />
|
||||
|
||||
/**
|
||||
* @param {Object} perfProfile The perf profile JSON object.
|
||||
* @return {Array<Object>} An array of recognized events that are captured
|
||||
* within the perf profile.
|
||||
*/
|
||||
export function convertPerfProfileToEvents(perfProfile: any): List<any> {
|
||||
var inProgressEvents = new Map(); // map from event name to start time
|
||||
var finishedEvents = []; // Array<Event> finished events
|
||||
var addFinishedEvent = function(eventName, startTime, endTime) {
|
||||
var categorizedEventName = categorizeEvent(eventName);
|
||||
var args = undefined;
|
||||
if (categorizedEventName == 'gc') {
|
||||
// TODO: We cannot measure heap size at the moment
|
||||
args = {usedHeapSize: 0};
|
||||
}
|
||||
if (startTime == endTime) {
|
||||
// Finished instantly
|
||||
finishedEvents.push({ph: 'X', ts: startTime, name: categorizedEventName, args: args});
|
||||
} else {
|
||||
// Has duration
|
||||
finishedEvents.push({ph: 'B', ts: startTime, name: categorizedEventName, args: args});
|
||||
finishedEvents.push({ph: 'E', ts: endTime, name: categorizedEventName, args: args});
|
||||
}
|
||||
};
|
||||
|
||||
var samples = perfProfile.threads[0].samples;
|
||||
// In perf profile, firefox samples all the frames in set time intervals. Here
|
||||
// we go through all the samples and construct the start and end time for each
|
||||
// event.
|
||||
for (var i = 0; i < samples.length; ++i) {
|
||||
var sample = samples[i];
|
||||
var sampleTime = sample.time;
|
||||
|
||||
// Add all the frames into a set so it's easier/faster to find the set
|
||||
// differences
|
||||
var sampleFrames = new Set();
|
||||
sample.frames.forEach(function(frame) { sampleFrames.add(frame.location); });
|
||||
|
||||
// If an event is in the inProgressEvents map, but not in the current sample,
|
||||
// then it must have just finished. We add this event to the finishedEvents
|
||||
// array and remove it from the inProgressEvents map.
|
||||
var previousSampleTime = (i == 0 ? /* not used */ -1 : samples[i - 1].time);
|
||||
inProgressEvents.forEach(function(startTime, eventName) {
|
||||
if (!(sampleFrames.has(eventName))) {
|
||||
addFinishedEvent(eventName, startTime, previousSampleTime);
|
||||
inProgressEvents.delete(eventName);
|
||||
}
|
||||
});
|
||||
|
||||
// If an event is in the current sample, but not in the inProgressEvents map,
|
||||
// then it must have just started. We add this event to the inProgressEvents
|
||||
// map.
|
||||
sampleFrames.forEach(function(eventName) {
|
||||
if (!(inProgressEvents.has(eventName))) {
|
||||
inProgressEvents.set(eventName, sampleTime);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// If anything is still in progress, we need to included it as a finished event
|
||||
// since recording ended.
|
||||
var lastSampleTime = samples[samples.length - 1].time;
|
||||
inProgressEvents.forEach(function(startTime, eventName) {
|
||||
addFinishedEvent(eventName, startTime, lastSampleTime);
|
||||
});
|
||||
|
||||
// Remove all the unknown categories.
|
||||
return finishedEvents.filter(function(event) { return event.name != 'unknown'; });
|
||||
}
|
||||
|
||||
// TODO: this is most likely not exhaustive.
|
||||
export function categorizeEvent(eventName: string): string {
|
||||
if (eventName.indexOf('PresShell::Paint') > -1) {
|
||||
return 'render';
|
||||
} else if (eventName.indexOf('FirefoxDriver.prototype.executeScript') > -1) {
|
||||
return 'script';
|
||||
} else if (eventName.indexOf('forceGC') > -1) {
|
||||
return 'gc';
|
||||
} else {
|
||||
return 'unknown';
|
||||
}
|
||||
}
|
|
@ -1,5 +1 @@
|
|||
{
|
||||
"version": "0.0.1",
|
||||
"main": "lib/main.js",
|
||||
"name": "ffperf-addon"
|
||||
}
|
||||
{ "version" : "0.0.1", "main" : "lib/main.js", "name" : "ffperf-addon" }
|
||||
|
|
|
@ -12,6 +12,7 @@ import {Validator} from './validator';
|
|||
import {PerflogMetric} from './metric/perflog_metric';
|
||||
import {MultiMetric} from './metric/multi_metric';
|
||||
import {ChromeDriverExtension} from './webdriver/chrome_driver_extension';
|
||||
import {FirefoxDriverExtension} from './webdriver/firefox_driver_extension';
|
||||
import {IOsDriverExtension} from './webdriver/ios_driver_extension';
|
||||
import {WebDriverExtension} from './web_driver_extension';
|
||||
import {SampleDescription} from './sample_description';
|
||||
|
@ -62,6 +63,7 @@ var _DEFAULT_BINDINGS = [
|
|||
RegressionSlopeValidator.BINDINGS,
|
||||
SizeValidator.BINDINGS,
|
||||
ChromeDriverExtension.BINDINGS,
|
||||
FirefoxDriverExtension.BINDINGS,
|
||||
IOsDriverExtension.BINDINGS,
|
||||
PerflogMetric.BINDINGS,
|
||||
SampleDescription.BINDINGS,
|
||||
|
@ -70,7 +72,7 @@ var _DEFAULT_BINDINGS = [
|
|||
|
||||
Reporter.bindTo(MultiReporter),
|
||||
Validator.bindTo(RegressionSlopeValidator),
|
||||
WebDriverExtension.bindTo([ChromeDriverExtension, IOsDriverExtension]),
|
||||
WebDriverExtension.bindTo([ChromeDriverExtension, FirefoxDriverExtension, IOsDriverExtension]),
|
||||
Metric.bindTo(MultiMetric),
|
||||
|
||||
bind(Options.CAPABILITIES)
|
||||
|
|
|
@ -16,6 +16,7 @@ export class WebDriverAdapter {
|
|||
|
||||
waitFor(callback: Function): Promise<any> { throw new BaseException('NYI'); }
|
||||
executeScript(script: string): Promise<any> { throw new BaseException('NYI'); }
|
||||
executeAsyncScript(script: string): Promise<any> { throw new BaseException('NYI'); }
|
||||
capabilities(): Promise<Map<string, any>> { throw new BaseException('NYI'); }
|
||||
logs(type: string): Promise<List<any>> { throw new BaseException('NYI'); }
|
||||
}
|
||||
|
|
|
@ -16,6 +16,10 @@ class AsyncWebDriverAdapter extends WebDriverAdapter {
|
|||
return _driver.execute(script, const []);
|
||||
}
|
||||
|
||||
Future executeAsyncScript(String script) {
|
||||
return _driver.executeAsync(script, const []);
|
||||
}
|
||||
|
||||
Future<Map> capabilities() {
|
||||
return new Future.value(_driver.capabilities);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
import {bind, Binding} from 'angular2/di';
|
||||
import {isPresent, StringWrapper} from 'angular2/src/facade/lang';
|
||||
import {WebDriverExtension, PerfLogFeatures} from '../web_driver_extension';
|
||||
import {WebDriverAdapter} from '../web_driver_adapter';
|
||||
import {Promise} from 'angular2/src/facade/async';
|
||||
|
||||
export class FirefoxDriverExtension extends WebDriverExtension {
|
||||
static get BINDINGS(): List<Binding> { return _BINDINGS; }
|
||||
|
||||
private _profilerStarted: boolean;
|
||||
|
||||
constructor(private _driver: WebDriverAdapter) {
|
||||
super();
|
||||
this._profilerStarted = false;
|
||||
}
|
||||
|
||||
gc() { return this._driver.executeScript('window.forceGC()'); }
|
||||
|
||||
timeBegin(name: string): Promise<any> {
|
||||
if (!this._profilerStarted) {
|
||||
this._profilerStarted = true;
|
||||
this._driver.executeScript('window.startProfiler();');
|
||||
}
|
||||
return this._driver.executeScript('window.markStart("' + name + '");');
|
||||
}
|
||||
|
||||
timeEnd(name: string, restartName: string = null): Promise<any> {
|
||||
var script = 'window.markEnd("' + name + '");';
|
||||
if (isPresent(restartName)) {
|
||||
script += 'window.markStart("' + restartName + '");';
|
||||
}
|
||||
return this._driver.executeScript(script);
|
||||
}
|
||||
|
||||
readPerfLog(): Promise<any> {
|
||||
return this._driver.executeAsyncScript('var cb = arguments[0]; window.getProfile(cb);');
|
||||
}
|
||||
|
||||
perfLogFeatures(): PerfLogFeatures { return new PerfLogFeatures({render: true, gc: true}); }
|
||||
|
||||
supports(capabilities: StringMap<string, any>): boolean {
|
||||
return StringWrapper.equals(capabilities['browserName'].toLowerCase(), 'firefox');
|
||||
}
|
||||
}
|
||||
|
||||
var _BINDINGS = [
|
||||
bind(FirefoxDriverExtension)
|
||||
.toFactory((driver) => new FirefoxDriverExtension(driver), [WebDriverAdapter])
|
||||
];
|
|
@ -30,6 +30,10 @@ export class SeleniumWebDriverAdapter extends WebDriverAdapter {
|
|||
return this._convertPromise(this._driver.executeScript(script));
|
||||
}
|
||||
|
||||
executeAsyncScript(script: string): Promise<any> {
|
||||
return this._convertPromise(this._driver.executeAsyncScript(script));
|
||||
}
|
||||
|
||||
capabilities(): Promise<any> {
|
||||
return this._convertPromise(
|
||||
this._driver.getCapabilities().then((capsObject) => capsObject.toJSON()));
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
/// <reference path="../../../angular2/typings/node/node.d.ts" />
|
||||
require('traceur/bin/traceur-runtime.js');
|
||||
require('reflect-metadata');
|
||||
var testHelper = require('../../src/firefox_extension/lib/test_helper.js');
|
||||
|
||||
// Where to save profile results (parent folder must exist)
|
||||
var PROFILE_SAVE_PATH = './perfProfile.json';
|
||||
|
||||
exports.config = {
|
||||
specs: ['spec.js'],
|
||||
specs: ['spec.js', 'sample_benchmark.js'],
|
||||
|
||||
getMultiCapabilities: function() { return testHelper.getFirefoxProfileWithExtension(); },
|
||||
framework: 'jasmine2',
|
||||
|
||||
params: {profileSavePath: testHelper.getAbsolutePath(PROFILE_SAVE_PATH)}
|
||||
jasmineNodeOpts: {showColors: true, defaultTimeoutInterval: 1200000},
|
||||
|
||||
getMultiCapabilities: function() { return testHelper.getFirefoxProfileWithExtension(); }
|
||||
};
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
library benchpress.test.firefox_extension.parser_util_spec;
|
||||
|
||||
main() {
|
||||
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
import {convertPerfProfileToEvents} from 'benchpress/src/firefox_extension/lib/parser_util';
|
||||
|
||||
function assertEventsEqual(actualEvents, expectedEvents) {
|
||||
expect(actualEvents.length == expectedEvents.length);
|
||||
for (var i = 0; i < actualEvents.length; ++i) {
|
||||
var actualEvent = actualEvents[i];
|
||||
var expectedEvent = expectedEvents[i];
|
||||
for (var key in actualEvent) {
|
||||
expect(actualEvent[key]).toEqual(expectedEvent[key]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export function main() {
|
||||
describe('convertPerfProfileToEvents', function() {
|
||||
it('should convert single instantaneous event', function() {
|
||||
var profileData = {
|
||||
threads: [
|
||||
{samples: [{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}]}
|
||||
]
|
||||
};
|
||||
var perfEvents = convertPerfProfileToEvents(profileData);
|
||||
assertEventsEqual(perfEvents, [{ph: 'X', ts: 1, name: 'script'}]);
|
||||
});
|
||||
|
||||
it('should convert single non-instantaneous event', function() {
|
||||
var profileData = {
|
||||
threads: [
|
||||
{
|
||||
samples: [
|
||||
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
|
||||
{time: 2, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
|
||||
{time: 100, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
var perfEvents = convertPerfProfileToEvents(profileData);
|
||||
assertEventsEqual(perfEvents,
|
||||
[{ph: 'B', ts: 1, name: 'script'}, {ph: 'E', ts: 100, name: 'script'}]);
|
||||
});
|
||||
|
||||
it('should convert multiple instantaneous events', function() {
|
||||
var profileData = {
|
||||
threads: [
|
||||
{
|
||||
samples: [
|
||||
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
|
||||
{time: 2, frames: [{location: 'PresShell::Paint'}]}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
var perfEvents = convertPerfProfileToEvents(profileData);
|
||||
assertEventsEqual(perfEvents,
|
||||
[{ph: 'X', ts: 1, name: 'script'}, {ph: 'X', ts: 2, name: 'render'}]);
|
||||
});
|
||||
|
||||
it('should convert multiple mixed events', function() {
|
||||
var profileData = {
|
||||
threads: [
|
||||
{
|
||||
samples: [
|
||||
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
|
||||
{time: 2, frames: [{location: 'PresShell::Paint'}]},
|
||||
{time: 5, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
|
||||
{time: 10, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
var perfEvents = convertPerfProfileToEvents(profileData);
|
||||
assertEventsEqual(perfEvents, [
|
||||
{ph: 'X', ts: 1, name: 'script'},
|
||||
{ph: 'X', ts: 2, name: 'render'},
|
||||
{ph: 'B', ts: 5, name: 'script'},
|
||||
{ph: 'E', ts: 10, name: 'script'}
|
||||
]);
|
||||
});
|
||||
|
||||
it('should add args to gc events', function() {
|
||||
var profileData = {threads: [{samples: [{time: 1, frames: [{location: 'forceGC'}]}]}]};
|
||||
var perfEvents = convertPerfProfileToEvents(profileData);
|
||||
assertEventsEqual(perfEvents, [{ph: 'X', ts: 1, name: 'gc', args: {usedHeapSize: 0}}]);
|
||||
});
|
||||
|
||||
it('should skip unknown events', function() {
|
||||
var profileData = {
|
||||
threads: [
|
||||
{
|
||||
samples: [
|
||||
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
|
||||
{time: 2, frames: [{location: 'foo'}]}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
||||
var perfEvents = convertPerfProfileToEvents(profileData);
|
||||
assertEventsEqual(perfEvents, [{ph: 'X', ts: 1, name: 'script'}]);
|
||||
});
|
||||
});
|
||||
};
|
|
@ -0,0 +1,5 @@
|
|||
library benchpress.test.firefox_extension.sample_benchmark;
|
||||
|
||||
main() {
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
var benchpress = require('../../index.js');
|
||||
var runner = new benchpress.Runner([
|
||||
// use protractor as Webdriver client
|
||||
benchpress.SeleniumWebDriverAdapter.PROTRACTOR_BINDINGS,
|
||||
// use RegressionSlopeValidator to validate samples
|
||||
benchpress.Validator.bindTo(benchpress.RegressionSlopeValidator),
|
||||
// use 10 samples to calculate slope regression
|
||||
benchpress.bind(benchpress.RegressionSlopeValidator.SAMPLE_SIZE).toValue(20),
|
||||
// use the script metric to calculate slope regression
|
||||
benchpress.bind(benchpress.RegressionSlopeValidator.METRIC).toValue('scriptTime'),
|
||||
benchpress.bind(benchpress.Options.FORCE_GC).toValue(true)
|
||||
]);
|
||||
|
||||
describe('deep tree baseline', function() {
|
||||
it('should be fast!', function(done) {
|
||||
browser.ignoreSynchronization = true;
|
||||
browser.get('http://localhost:8001/examples/src/benchpress/');
|
||||
|
||||
/*
|
||||
* Tell benchpress to click the buttons to destroy and re-create the tree for each sample.
|
||||
* Benchpress will log the collected metrics after each sample is collected, and will stop
|
||||
* sampling as soon as the calculated regression slope for last 20 samples is stable.
|
||||
*/
|
||||
runner.sample({
|
||||
id: 'baseline',
|
||||
execute: function() { $('button')
|
||||
.click(); },
|
||||
bindings: [benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue({depth: 9})]
|
||||
})
|
||||
.then(done, done.fail);
|
||||
});
|
||||
});
|
|
@ -1,2 +1,5 @@
|
|||
library benchpress.test.firefox_extension.spec;
|
||||
//no dart implementation
|
||||
|
||||
main() {
|
||||
|
||||
}
|
||||
|
|
|
@ -2,26 +2,15 @@
|
|||
/// <reference path="../../../angular2/typings/angular-protractor/angular-protractor.d.ts" />
|
||||
/// <reference path="../../../angular2/typings/jasmine/jasmine.d.ts" />
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
var validateFile = function() {
|
||||
try {
|
||||
var content = fs.readFileSync(browser.params.profileSavePath, 'utf8');
|
||||
// TODO(hankduan): This check is not very useful. Ideally we want to
|
||||
// validate that the file contains all the events that we are looking for.
|
||||
// Pending on data transformer.
|
||||
expect(content).toContain('forceGC');
|
||||
// Delete file
|
||||
fs.unlinkSync(browser.params.profileSavePath);
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') {
|
||||
// If files doesn't exist
|
||||
console.error('Error: firefox extension did not save profile JSON');
|
||||
} else {
|
||||
console.error('Error: ' + err);
|
||||
var assertEventsContainsName = function(events, eventName) {
|
||||
var found = false;
|
||||
for (var i = 0; i < events.length; ++i) {
|
||||
if (events[i].name == eventName) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
expect(found).toBeTruthy();
|
||||
};
|
||||
|
||||
describe('firefox extension', function() {
|
||||
|
@ -37,10 +26,10 @@ describe('firefox extension', function() {
|
|||
|
||||
browser.executeScript('window.forceGC()');
|
||||
|
||||
var script = 'window.stopAndRecord("' + browser.params.profileSavePath + '")';
|
||||
browser.executeScript(script).then(function() { console.log('stopped measuring perf'); });
|
||||
|
||||
// wait for it to finish, then validate file.
|
||||
browser.sleep(3000).then(validateFile);
|
||||
browser.executeAsyncScript('var cb = arguments[0]; window.getProfile(cb);')
|
||||
.then(function(profile) {
|
||||
assertEventsContainsName(profile, 'gc');
|
||||
assertEventsContainsName(profile, 'script');
|
||||
});
|
||||
})
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue