2b45a01517
We have made good progress on object literals as well, although there are still a lot that use the old style, given how ubiquitous object literals are. But the needed reindentation isn't overly intrusive, as changes are limited to the object literals themselves (i.e. they don't affect surrounding code). And given that object literals account for quite a bit of the remaining differences between regular and legacy rules, doing the transition now is still worthwhile. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2200>
272 lines
9.2 KiB
JavaScript
272 lines
9.2 KiB
JavaScript
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
|
|
/* exported run, script_overviewShowStart, script_overviewShowDone,
|
|
script_applicationsShowStart, script_applicationsShowDone,
|
|
script_afterShowHide, malloc_usedSize, glx_swapComplete,
|
|
clutter_stagePaintDone */
|
|
/* eslint camelcase: ["error", { properties: "never", allow: ["^script_", "^malloc", "^glx", "^clutter"] }] */
|
|
|
|
const System = imports.system;
|
|
|
|
const Main = imports.ui.main;
|
|
const Scripting = imports.ui.scripting;
|
|
|
|
// This performance script measure the most important (core) performance
|
|
// metrics for the shell. By looking at the output metrics of this script
|
|
// someone should be able to get an idea of how well the shell is performing
|
|
// on a particular system.
|
|
|
|
var METRICS = {
|
|
overviewLatencyFirst: {
|
|
description: 'Time to first frame after triggering overview, first time',
|
|
units: 'us',
|
|
},
|
|
overviewFpsFirst: {
|
|
description: 'Frame rate when going to the overview, first time',
|
|
units: 'frames / s',
|
|
},
|
|
overviewLatencySubsequent: {
|
|
description: 'Time to first frame after triggering overview, second time',
|
|
units: 'us',
|
|
},
|
|
overviewFpsSubsequent: {
|
|
description: 'Frames rate when going to the overview, second time',
|
|
units: 'frames / s',
|
|
},
|
|
overviewFps5Windows: {
|
|
description: 'Frames rate when going to the overview, 5 windows open',
|
|
units: 'frames / s',
|
|
},
|
|
overviewFps10Windows: {
|
|
description: 'Frames rate when going to the overview, 10 windows open',
|
|
units: 'frames / s',
|
|
},
|
|
overviewFps5Maximized: {
|
|
description: 'Frames rate when going to the overview, 5 maximized windows open',
|
|
units: 'frames / s',
|
|
},
|
|
overviewFps10Maximized: {
|
|
description: 'Frames rate when going to the overview, 10 maximized windows open',
|
|
units: 'frames / s',
|
|
},
|
|
overviewFps5Alpha: {
|
|
description: 'Frames rate when going to the overview, 5 alpha-transparent windows open',
|
|
units: 'frames / s',
|
|
},
|
|
overviewFps10Alpha: {
|
|
description: 'Frames rate when going to the overview, 10 alpha-transparent windows open',
|
|
units: 'frames / s',
|
|
},
|
|
usedAfterOverview: {
|
|
description: "Malloc'ed bytes after the overview is shown once",
|
|
units: 'B',
|
|
},
|
|
leakedAfterOverview: {
|
|
description: "Additional malloc'ed bytes the second time the overview is shown",
|
|
units: 'B',
|
|
},
|
|
applicationsShowTimeFirst: {
|
|
description: 'Time to switch to applications view, first time',
|
|
units: 'us',
|
|
},
|
|
applicationsShowTimeSubsequent: {
|
|
description: 'Time to switch to applications view, second time',
|
|
units: 'us',
|
|
},
|
|
};
|
|
|
|
const WINDOW_CONFIGS = [{
|
|
width: 640, height: 480,
|
|
alpha: false, maximized: false, count: 1, metric: 'overviewFpsSubsequent',
|
|
}, {
|
|
width: 640, height: 480,
|
|
alpha: false, maximized: false, count: 5, metric: 'overviewFps5Windows',
|
|
}, {
|
|
width: 640, height: 480,
|
|
alpha: false, maximized: false, count: 10, metric: 'overviewFps10Windows',
|
|
}, {
|
|
width: 640, height: 480,
|
|
alpha: false, maximized: true, count: 5, metric: 'overviewFps5Maximized',
|
|
}, {
|
|
width: 640, height: 480,
|
|
alpha: false, maximized: true, count: 10, metric: 'overviewFps10Maximized',
|
|
}, {
|
|
width: 640, height: 480,
|
|
alpha: true, maximized: false, count: 5, metric: 'overviewFps5Alpha',
|
|
}, {
|
|
width: 640, height: 480,
|
|
alpha: true, maximized: false, count: 10, metric: 'overviewFps10Alpha',
|
|
}];
|
|
|
|
async function run() {
|
|
/* eslint-disable no-await-in-loop */
|
|
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
|
|
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
|
|
Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview");
|
|
Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view");
|
|
Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view");
|
|
|
|
// Enable recording of timestamps for different points in the frame cycle
|
|
global.frame_timestamps = true;
|
|
|
|
Main.overview.connect('shown', () => {
|
|
Scripting.scriptEvent('overviewShowDone');
|
|
});
|
|
|
|
await Scripting.sleep(1000);
|
|
|
|
for (let i = 0; i < 2 * WINDOW_CONFIGS.length; i++) {
|
|
// We go to the overview twice for each configuration; the first time
|
|
// to calculate the mipmaps for the windows, the second time to get
|
|
// a clean set of numbers.
|
|
if ((i % 2) == 0) {
|
|
let config = WINDOW_CONFIGS[i / 2];
|
|
await Scripting.destroyTestWindows();
|
|
|
|
for (let k = 0; k < config.count; k++) {
|
|
await Scripting.createTestWindow({
|
|
width: config.width,
|
|
height: config.height,
|
|
alpha: config.alpha,
|
|
maximized: config.maximized,
|
|
});
|
|
}
|
|
|
|
await Scripting.waitTestWindows();
|
|
await Scripting.sleep(1000);
|
|
await Scripting.waitLeisure();
|
|
}
|
|
|
|
Scripting.scriptEvent('overviewShowStart');
|
|
Main.overview.show();
|
|
|
|
await Scripting.waitLeisure();
|
|
Main.overview.hide();
|
|
await Scripting.waitLeisure();
|
|
|
|
System.gc();
|
|
await Scripting.sleep(1000);
|
|
Scripting.collectStatistics();
|
|
Scripting.scriptEvent('afterShowHide');
|
|
}
|
|
|
|
await Scripting.destroyTestWindows();
|
|
await Scripting.sleep(1000);
|
|
|
|
Main.overview.show();
|
|
await Scripting.waitLeisure();
|
|
|
|
for (let i = 0; i < 2; i++) {
|
|
Scripting.scriptEvent('applicationsShowStart');
|
|
// eslint-disable-next-line require-atomic-updates
|
|
Main.overview.dash.showAppsButton.checked = true;
|
|
await Scripting.waitLeisure();
|
|
Scripting.scriptEvent('applicationsShowDone');
|
|
// eslint-disable-next-line require-atomic-updates
|
|
Main.overview.dash.showAppsButton.checked = false;
|
|
await Scripting.waitLeisure();
|
|
}
|
|
/* eslint-enable no-await-in-loop */
|
|
}
|
|
|
|
let showingOverview = false;
|
|
let finishedShowingOverview = false;
|
|
let overviewShowStart;
|
|
let overviewFrames;
|
|
let overviewLatency;
|
|
let mallocUsedSize = 0;
|
|
let overviewShowCount = 0;
|
|
let haveSwapComplete = false;
|
|
let applicationsShowStart;
|
|
let applicationsShowCount = 0;
|
|
|
|
function script_overviewShowStart(time) {
|
|
showingOverview = true;
|
|
finishedShowingOverview = false;
|
|
overviewShowStart = time;
|
|
overviewFrames = 0;
|
|
}
|
|
|
|
function script_overviewShowDone(_time) {
|
|
// We've set up the state at the end of the zoom out, but we
|
|
// need to wait for one more frame to paint before we count
|
|
// ourselves as done.
|
|
finishedShowingOverview = true;
|
|
}
|
|
|
|
function script_applicationsShowStart(time) {
|
|
applicationsShowStart = time;
|
|
}
|
|
|
|
function script_applicationsShowDone(time) {
|
|
applicationsShowCount++;
|
|
if (applicationsShowCount == 1)
|
|
METRICS.applicationsShowTimeFirst.value = time - applicationsShowStart;
|
|
else
|
|
METRICS.applicationsShowTimeSubsequent.value = time - applicationsShowStart;
|
|
}
|
|
|
|
function script_afterShowHide(_time) {
|
|
if (overviewShowCount == 1)
|
|
METRICS.usedAfterOverview.value = mallocUsedSize;
|
|
else
|
|
METRICS.leakedAfterOverview.value = mallocUsedSize - METRICS.usedAfterOverview.value;
|
|
}
|
|
|
|
function malloc_usedSize(time, bytes) {
|
|
mallocUsedSize = bytes;
|
|
}
|
|
|
|
function _frameDone(time) {
|
|
if (showingOverview) {
|
|
if (overviewFrames == 0)
|
|
overviewLatency = time - overviewShowStart;
|
|
|
|
overviewFrames++;
|
|
}
|
|
|
|
if (finishedShowingOverview) {
|
|
showingOverview = false;
|
|
finishedShowingOverview = false;
|
|
overviewShowCount++;
|
|
|
|
let dt = (time - (overviewShowStart + overviewLatency)) / 1000000;
|
|
|
|
// If we see a start frame and an end frame, that would
|
|
// be 1 frame for a FPS computation, hence the '- 1'
|
|
let fps = (overviewFrames - 1) / dt;
|
|
|
|
if (overviewShowCount == 1) {
|
|
METRICS.overviewLatencyFirst.value = overviewLatency;
|
|
METRICS.overviewFpsFirst.value = fps;
|
|
} else if (overviewShowCount == 2) {
|
|
METRICS.overviewLatencySubsequent.value = overviewLatency;
|
|
}
|
|
|
|
// Other than overviewFpsFirst, we collect FPS metrics the second
|
|
// we show each window configuration. overviewShowCount is 1,2,3...
|
|
if (overviewShowCount % 2 == 0) {
|
|
let config = WINDOW_CONFIGS[(overviewShowCount / 2) - 1];
|
|
METRICS[config.metric].value = fps;
|
|
}
|
|
}
|
|
}
|
|
|
|
function glx_swapComplete(time, swapTime) {
|
|
haveSwapComplete = true;
|
|
|
|
_frameDone(swapTime);
|
|
}
|
|
|
|
function clutter_stagePaintDone(time) {
|
|
// If we aren't receiving GLXBufferSwapComplete events, then we approximate
|
|
// the time the user sees a frame with the time we finished doing drawing
|
|
// commands for the frame. This doesn't take into account the time for
|
|
// the GPU to finish painting, and the time for waiting for the buffer
|
|
// swap, but if this are uniform - every frame takes the same time to draw -
|
|
// then it won't upset our FPS calculation, though the latency value
|
|
// will be slightly too low.
|
|
|
|
if (!haveSwapComplete)
|
|
_frameDone(time);
|
|
}
|