refactor(benchpress): delete broken code (#35922)

PR Close #35922
This commit is contained in:
Wagner Maciel 2020-03-06 15:55:56 -08:00 committed by Misko Hevery
parent 8968b206b4
commit 989dea7083
10 changed files with 0 additions and 475 deletions

View File

@ -1,2 +0,0 @@
*.xpi
addon-sdk*

View File

@ -1,38 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
declare var exportFunction: any;
declare var unsafeWindow: any;
exportFunction(function() {
const curTime = unsafeWindow.performance.now();
(<any>self).port.emit('startProfiler', curTime);
}, unsafeWindow, {defineAs: 'startProfiler'});
exportFunction(function() {
(<any>self).port.emit('stopProfiler');
}, unsafeWindow, {defineAs: 'stopProfiler'});
exportFunction(function(cb: Function) {
(<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: string) {
const curTime = unsafeWindow.performance.now();
(<any>self).port.emit('markStart', name, curTime);
}, unsafeWindow, {defineAs: 'markStart'});
exportFunction(function(name: string) {
const curTime = unsafeWindow.performance.now();
(<any>self).port.emit('markEnd', name, curTime);
}, unsafeWindow, {defineAs: 'markEnd'});

View File

@ -1,80 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const {Cc, Ci, Cu} = require('chrome');
const os = Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
const ParserUtil = require('./parser_util');
class Profiler {
private _profiler: any;
// TODO(issue/24571): remove '!'.
private _markerEvents !: any[];
// TODO(issue/24571): remove '!'.
private _profilerStartTime !: number;
constructor() { this._profiler = Cc['@mozilla.org/tools/profiler;1'].getService(Ci.nsIProfiler); }
start(entries: any, interval: any, features: any, timeStarted: any) {
this._profiler.StartProfiler(entries, interval, features, features.length);
this._profilerStartTime = timeStarted;
this._markerEvents = [];
}
stop() { this._profiler.StopProfiler(); }
getProfilePerfEvents() {
const profileData = this._profiler.getProfileData();
let perfEvents = ParserUtil.convertPerfProfileToEvents(profileData);
perfEvents = this._mergeMarkerEvents(perfEvents);
perfEvents.sort(function(event1: any, event2: any) {
return event1.ts - event2.ts;
}); // Sort by ts
return perfEvents;
}
/** @internal */
private _mergeMarkerEvents(perfEvents: any[]): 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();
os.notifyObservers(null, 'child-gc-request', null);
}
const mod = require('sdk/page-mod');
const data = require('sdk/self').data;
const profiler = new Profiler();
mod.PageMod({
include: ['*'],
contentScriptFile: data.url('installed_script.js'),
onAttach: (worker: any) => {
worker.port.on(
'startProfiler',
(timeStarted: any) => profiler.start(
/* = profiler memory */ 3000000, 0.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: string, timeStarted: any) => profiler.addStartEvent(name, timeStarted));
worker.port.on(
'markEnd', (name: string, timeEnded: any) => profiler.addEndEvent(name, timeEnded));
}
});

View File

@ -1,92 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/**
* @param {Object} perfProfile The perf profile JSON object.
* @return {Object[]} An array of recognized events that are captured
* within the perf profile.
*/
export function convertPerfProfileToEvents(perfProfile: any): any[] {
const inProgressEvents = new Map(); // map from event name to start time
const finishedEvents: {[key: string]: any}[] = []; // Event[] finished events
const addFinishedEvent = function(eventName: string, startTime: number, endTime: number) {
const categorizedEventName = categorizeEvent(eventName);
let args: {[key: string]: any}|undefined = 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});
}
};
const 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 (let i = 0; i < samples.length; ++i) {
const sample = samples[i];
const sampleTime = sample.time;
// Add all the frames into a set so it's easier/faster to find the set
// differences
const sampleFrames = new Set();
sample.frames.forEach(function(frame: {[key: string]: any}) {
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.
const 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.
const 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';
}
}

View File

@ -1,51 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
const q = require('q');
const FirefoxProfile = require('firefox-profile');
const jpm = require('jpm/lib/xpi');
const pathUtil = require('path');
const PERF_ADDON_PACKAGE_JSON_DIR = '..';
exports.getAbsolutePath = function(path: string) {
const normalizedPath = pathUtil.normalize(path);
if (pathUtil.resolve(normalizedPath) == normalizedPath) {
// Already absolute path
return normalizedPath;
} else {
return pathUtil.join(__dirname, normalizedPath);
}
};
exports.getFirefoxProfile = function(extensionPath: string) {
const deferred = q.defer();
const firefoxProfile = new FirefoxProfile();
firefoxProfile.addExtensions([extensionPath], () => {
firefoxProfile.encoded((err: any, encodedProfile: string) => {
const multiCapabilities = [{browserName: 'firefox', firefox_profile: encodedProfile}];
deferred.resolve(multiCapabilities);
});
});
return deferred.promise;
};
exports.getFirefoxProfileWithExtension = function() {
const absPackageJsonDir = pathUtil.join(__dirname, PERF_ADDON_PACKAGE_JSON_DIR);
const packageJson = require(pathUtil.join(absPackageJsonDir, 'package.json'));
const savedCwd = process.cwd();
process.chdir(absPackageJsonDir);
return jpm(packageJson).then((xpiPath: string) => {
process.chdir(savedCwd);
return exports.getFirefoxProfile(xpiPath);
});
};

View File

@ -1 +0,0 @@
{ "version" : "0.0.1", "main" : "lib/main.js", "name" : "ffperf-addon" }

View File

@ -1,21 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
require('core-js');
require('reflect-metadata');
const testHelper = require('../../src/firefox_extension/lib/test_helper.js');
exports.config = {
specs: ['spec.js', 'sample_benchmark.js'],
framework: 'jasmine2',
jasmineNodeOpts: {showColors: true, defaultTimeoutInterval: 1200000},
getMultiCapabilities: function() { return testHelper.getFirefoxProfileWithExtension(); }
};

View File

@ -1,100 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {convertPerfProfileToEvents} from '../../src/firefox_extension/lib/parser_util';
function assertEventsEqual(actualEvents: any[], expectedEvents: any[]) {
expect(actualEvents.length == expectedEvents.length);
for (let i = 0; i < actualEvents.length; ++i) {
const actualEvent = actualEvents[i];
const expectedEvent = expectedEvents[i];
for (const key in actualEvent) {
expect(actualEvent[key]).toEqual(expectedEvent[key]);
}
}
}
{
describe('convertPerfProfileToEvents', function() {
it('should convert single instantaneous event', function() {
const profileData = {
threads: [
{samples: [{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}]}
]
};
const perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, [{ph: 'X', ts: 1, name: 'script'}]);
});
it('should convert single non-instantaneous event', function() {
const profileData = {
threads: [{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 100, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]}
]
}]
};
const perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(
perfEvents, [{ph: 'B', ts: 1, name: 'script'}, {ph: 'E', ts: 100, name: 'script'}]);
});
it('should convert multiple instantaneous events', function() {
const profileData = {
threads: [{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'PresShell::Paint'}]}
]
}]
};
const perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(
perfEvents, [{ph: 'X', ts: 1, name: 'script'}, {ph: 'X', ts: 2, name: 'render'}]);
});
it('should convert multiple mixed events', function() {
const 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'}]}
]
}]
};
const 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() {
const profileData = {threads: [{samples: [{time: 1, frames: [{location: 'forceGC'}]}]}]};
const perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, [{ph: 'X', ts: 1, name: 'gc', args: {usedHeapSize: 0}}]);
});
it('should skip unknown events', function() {
const profileData = {
threads: [{
samples: [
{time: 1, frames: [{location: 'FirefoxDriver.prototype.executeScript'}]},
{time: 2, frames: [{location: 'foo'}]}
]
}]
};
const perfEvents = convertPerfProfileToEvents(profileData);
assertEventsEqual(perfEvents, [{ph: 'X', ts: 1, name: 'script'}]);
});
});
}

View File

@ -1,45 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
import {$, browser} from 'protractor';
const benchpress = require('../../index.js');
// TODO: this test is currnetly failing. it seems that it didn't run on the ci for a while
xdescribe('deep tree baseline', function() {
const runner = new benchpress.Runner([
// use protractor as Webdriver client
benchpress.SeleniumWebDriverAdapter.PROTRACTOR_PROVIDERS,
// use RegressionSlopeValidator to validate samples
benchpress.Validator.bind(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)
]);
it('should be fast!', function(done) {
browser.ignoreSynchronization = true;
browser.get('http://localhost:8001/playground/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(); },
providers: [benchpress.bind(benchpress.Options.SAMPLE_DESCRIPTION).toValue({depth: 9})]
})
.then(done, done.fail);
});
});

View File

@ -1,45 +0,0 @@
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
/* tslint:disable:no-console */
import {browser} from 'protractor';
const assertEventsContainsName = function(events: any[], eventName: string) {
let found = false;
for (let i = 0; i < events.length; ++i) {
if (events[i].name == eventName) {
found = true;
break;
}
}
expect(found).toBeTruthy();
};
// TODO: this test is currnetly failing. it seems that it didn't run on the ci for a while
xdescribe('firefox extension', function() {
const TEST_URL = 'http://localhost:8001/playground/src/hello_world/index.html';
it('should measure performance', function() {
browser.sleep(3000); // wait for extension to load
browser.driver.get(TEST_URL);
browser.executeScript('window.startProfiler()').then(function() {
console.log('started measuring perf');
});
browser.executeAsyncScript('setTimeout(arguments[0], 1000);');
browser.executeScript('window.forceGC()');
browser.executeAsyncScript('var cb = arguments[0]; window.getProfile(cb);')
.then(function(profile: any) {
assertEventsContainsName(profile, 'gc');
assertEventsContainsName(profile, 'script');
});
});
});