Blame js/perf/core.js

Packit d345d1
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
Packit d345d1
Packit d345d1
const System = imports.system;
Packit d345d1
Packit d345d1
const Main = imports.ui.main;
Packit d345d1
const Scripting = imports.ui.scripting;
Packit d345d1
Packit d345d1
// This performance script measure the most important (core) performance
Packit d345d1
// metrics for the shell. By looking at the output metrics of this script
Packit d345d1
// someone should be able to get an idea of how well the shell is performing
Packit d345d1
// on a particular system.
Packit d345d1
Packit d345d1
var METRICS = {
Packit d345d1
    overviewLatencyFirst:
Packit d345d1
    { description: "Time to first frame after triggering overview, first time",
Packit d345d1
      units: "us" },
Packit d345d1
    overviewFpsFirst:
Packit d345d1
    { description: "Frame rate when going to the overview, first time",
Packit d345d1
      units: "frames / s" },
Packit d345d1
    overviewLatencySubsequent:
Packit d345d1
    { description: "Time to first frame after triggering overview, second time",
Packit d345d1
      units: "us"},
Packit d345d1
    overviewFpsSubsequent:
Packit d345d1
    { description: "Frames rate when going to the overview, second time",
Packit d345d1
      units: "frames / s" },
Packit d345d1
    overviewFps5Windows:
Packit d345d1
    { description: "Frames rate when going to the overview, 5 windows open",
Packit d345d1
      units: "frames / s" },
Packit d345d1
    overviewFps10Windows:
Packit d345d1
    { description: "Frames rate when going to the overview, 10 windows open",
Packit d345d1
      units: "frames / s" },
Packit d345d1
    overviewFps5Maximized:
Packit d345d1
    { description: "Frames rate when going to the overview, 5 maximized windows open",
Packit d345d1
      units: "frames / s" },
Packit d345d1
    overviewFps10Maximized:
Packit d345d1
    { description: "Frames rate when going to the overview, 10 maximized windows open",
Packit d345d1
      units: "frames / s" },
Packit d345d1
    overviewFps5Alpha:
Packit d345d1
    { description: "Frames rate when going to the overview, 5 alpha-transparent windows open",
Packit d345d1
      units: "frames / s" },
Packit d345d1
    overviewFps10Alpha:
Packit d345d1
    { description: "Frames rate when going to the overview, 10 alpha-transparent windows open",
Packit d345d1
      units: "frames / s" },
Packit d345d1
    usedAfterOverview:
Packit d345d1
    { description: "Malloc'ed bytes after the overview is shown once",
Packit d345d1
      units: "B" },
Packit d345d1
    leakedAfterOverview:
Packit d345d1
    { description: "Additional malloc'ed bytes the second time the overview is shown",
Packit d345d1
      units: "B" },
Packit d345d1
    applicationsShowTimeFirst:
Packit d345d1
    { description: "Time to switch to applications view, first time",
Packit d345d1
      units: "us" },
Packit d345d1
    applicationsShowTimeSubsequent:
Packit d345d1
    { description: "Time to switch to applications view, second time",
Packit d345d1
      units: "us"}
Packit d345d1
};
Packit d345d1
Packit d345d1
let WINDOW_CONFIGS = [
Packit d345d1
    { width: 640, height: 480, alpha: false, maximized: false, count: 1,  metric: 'overviewFpsSubsequent' },
Packit d345d1
    { width: 640, height: 480, alpha: false, maximized: false, count: 5,  metric: 'overviewFps5Windows'  },
Packit d345d1
    { width: 640, height: 480, alpha: false, maximized: false, count: 10, metric: 'overviewFps10Windows'  },
Packit d345d1
    { width: 640, height: 480, alpha: false, maximized: true,  count: 5,  metric: 'overviewFps5Maximized' },
Packit d345d1
    { width: 640, height: 480, alpha: false, maximized: true,  count: 10, metric: 'overviewFps10Maximized' },
Packit d345d1
    { width: 640, height: 480, alpha: true,  maximized: false, count: 5,  metric: 'overviewFps5Alpha' },
Packit d345d1
    { width: 640, height: 480, alpha: true,  maximized: false, count: 10, metric: 'overviewFps10Alpha' }
Packit d345d1
];
Packit d345d1
Packit d345d1
function *run() {
Packit d345d1
    Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Packit d345d1
    Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
Packit d345d1
    Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview");
Packit d345d1
    Scripting.defineScriptEvent("applicationsShowStart", "Starting to switch to applications view");
Packit d345d1
    Scripting.defineScriptEvent("applicationsShowDone", "Done switching to applications view");
Packit d345d1
Packit d345d1
    // Enable recording of timestamps for different points in the frame cycle
Packit d345d1
    global.frame_timestamps = true;
Packit d345d1
Packit d345d1
    Main.overview.connect('shown', () => {
Packit d345d1
        Scripting.scriptEvent('overviewShowDone');
Packit d345d1
    });
Packit d345d1
Packit d345d1
    yield Scripting.sleep(1000);
Packit d345d1
Packit d345d1
    for (let i = 0; i < 2 * WINDOW_CONFIGS.length; i++) {
Packit d345d1
        // We go to the overview twice for each configuration; the first time
Packit d345d1
        // to calculate the mipmaps for the windows, the second time to get
Packit d345d1
        // a clean set of numbers.
Packit d345d1
        if ((i % 2) == 0) {
Packit d345d1
            let config = WINDOW_CONFIGS[i / 2];
Packit d345d1
            yield Scripting.destroyTestWindows();
Packit d345d1
Packit d345d1
            for (let k = 0; k < config.count; k++)
Packit d345d1
                yield Scripting.createTestWindow({ width: config.width,
Packit d345d1
                                                   height: config.height,
Packit d345d1
                                                   alpha: config.alpha,
Packit d345d1
                                                   maximized: config.maximized });
Packit d345d1
Packit d345d1
            yield Scripting.waitTestWindows();
Packit d345d1
            yield Scripting.sleep(1000);
Packit d345d1
            yield Scripting.waitLeisure();
Packit d345d1
        }
Packit d345d1
Packit d345d1
        Scripting.scriptEvent('overviewShowStart');
Packit d345d1
        Main.overview.show();
Packit d345d1
Packit d345d1
        yield Scripting.waitLeisure();
Packit d345d1
        Main.overview.hide();
Packit d345d1
        yield Scripting.waitLeisure();
Packit d345d1
Packit d345d1
        System.gc();
Packit d345d1
        yield Scripting.sleep(1000);
Packit d345d1
        Scripting.collectStatistics();
Packit d345d1
        Scripting.scriptEvent('afterShowHide');
Packit d345d1
    }
Packit d345d1
Packit d345d1
    yield Scripting.destroyTestWindows();
Packit d345d1
    yield Scripting.sleep(1000);
Packit d345d1
Packit d345d1
    Main.overview.show();
Packit d345d1
    yield Scripting.waitLeisure();
Packit d345d1
Packit d345d1
    for (let i = 0; i < 2; i++) {
Packit d345d1
        Scripting.scriptEvent('applicationsShowStart');
Packit d345d1
        Main.overview._dash.showAppsButton.checked = true;
Packit d345d1
        yield Scripting.waitLeisure();
Packit d345d1
        Scripting.scriptEvent('applicationsShowDone');
Packit d345d1
        Main.overview._dash.showAppsButton.checked = false;
Packit d345d1
        yield Scripting.waitLeisure();
Packit d345d1
    }
Packit d345d1
}
Packit d345d1
Packit d345d1
let showingOverview = false;
Packit d345d1
let finishedShowingOverview = false;
Packit d345d1
let overviewShowStart;
Packit d345d1
let overviewFrames;
Packit d345d1
let overviewLatency;
Packit d345d1
let mallocUsedSize = 0;
Packit d345d1
let overviewShowCount = 0;
Packit d345d1
let firstOverviewUsedSize;
Packit d345d1
let haveSwapComplete = false;
Packit d345d1
let applicationsShowStart;
Packit d345d1
let applicationsShowCount = 0;
Packit d345d1
Packit d345d1
function script_overviewShowStart(time) {
Packit d345d1
    showingOverview = true;
Packit d345d1
    finishedShowingOverview = false;
Packit d345d1
    overviewShowStart = time;
Packit d345d1
    overviewFrames = 0;
Packit d345d1
}
Packit d345d1
Packit d345d1
function script_overviewShowDone(time) {
Packit d345d1
    // We've set up the state at the end of the zoom out, but we
Packit d345d1
    // need to wait for one more frame to paint before we count
Packit d345d1
    // ourselves as done.
Packit d345d1
    finishedShowingOverview = true;
Packit d345d1
}
Packit d345d1
Packit d345d1
function script_applicationsShowStart(time) {
Packit d345d1
    applicationsShowStart = time;
Packit d345d1
}
Packit d345d1
Packit d345d1
function script_applicationsShowDone(time) {
Packit d345d1
    applicationsShowCount++;
Packit d345d1
    if (applicationsShowCount == 1)
Packit d345d1
        METRICS.applicationsShowTimeFirst.value = time - applicationsShowStart;
Packit d345d1
    else
Packit d345d1
        METRICS.applicationsShowTimeSubsequent.value = time - applicationsShowStart;
Packit d345d1
}
Packit d345d1
Packit d345d1
function script_afterShowHide(time) {
Packit d345d1
    if (overviewShowCount == 1) {
Packit d345d1
        METRICS.usedAfterOverview.value = mallocUsedSize;
Packit d345d1
    } else {
Packit d345d1
        METRICS.leakedAfterOverview.value = mallocUsedSize - METRICS.usedAfterOverview.value;
Packit d345d1
    }
Packit d345d1
}
Packit d345d1
Packit d345d1
function malloc_usedSize(time, bytes) {
Packit d345d1
    mallocUsedSize = bytes;
Packit d345d1
}
Packit d345d1
Packit d345d1
function _frameDone(time) {
Packit d345d1
    if (showingOverview) {
Packit d345d1
        if (overviewFrames == 0)
Packit d345d1
            overviewLatency = time - overviewShowStart;
Packit d345d1
Packit d345d1
        overviewFrames++;
Packit d345d1
    }
Packit d345d1
Packit d345d1
    if (finishedShowingOverview) {
Packit d345d1
        showingOverview = false;
Packit d345d1
        finishedShowingOverview = false;
Packit d345d1
        overviewShowCount++;
Packit d345d1
Packit d345d1
        let dt = (time - (overviewShowStart + overviewLatency)) / 1000000;
Packit d345d1
Packit d345d1
        // If we see a start frame and an end frame, that would
Packit d345d1
        // be 1 frame for a FPS computation, hence the '- 1'
Packit d345d1
        let fps = (overviewFrames - 1) / dt;
Packit d345d1
Packit d345d1
        if (overviewShowCount == 1) {
Packit d345d1
            METRICS.overviewLatencyFirst.value = overviewLatency;
Packit d345d1
            METRICS.overviewFpsFirst.value = fps;
Packit d345d1
        } else if (overviewShowCount == 2) {
Packit d345d1
            METRICS.overviewLatencySubsequent.value = overviewLatency;
Packit d345d1
        }
Packit d345d1
Packit d345d1
        // Other than overviewFpsFirst, we collect FPS metrics the second
Packit d345d1
        // we show each window configuration. overviewShowCount is 1,2,3...
Packit d345d1
        if (overviewShowCount % 2 == 0) {
Packit d345d1
            let config = WINDOW_CONFIGS[(overviewShowCount / 2) - 1];
Packit d345d1
            METRICS[config.metric].value = fps;
Packit d345d1
        }
Packit d345d1
    }
Packit d345d1
}
Packit d345d1
Packit d345d1
function glx_swapComplete(time, swapTime) {
Packit d345d1
    haveSwapComplete = true;
Packit d345d1
Packit d345d1
    _frameDone(swapTime);
Packit d345d1
}
Packit d345d1
Packit d345d1
function clutter_stagePaintDone(time) {
Packit d345d1
    // If we aren't receiving GLXBufferSwapComplete events, then we approximate
Packit d345d1
    // the time the user sees a frame with the time we finished doing drawing
Packit d345d1
    // commands for the frame. This doesn't take into account the time for
Packit d345d1
    // the GPU to finish painting, and the time for waiting for the buffer
Packit d345d1
    // swap, but if this are uniform - every frame takes the same time to draw -
Packit d345d1
    // then it won't upset our FPS calculation, though the latency value
Packit d345d1
    // will be slightly too low.
Packit d345d1
Packit d345d1
    if (!haveSwapComplete)
Packit d345d1
        _frameDone(time);
Packit d345d1
}