Bug 1633625 - Extract out a load cycle manager r=jonco

Differential Revision: https://phabricator.services.mozilla.com/D73981
This commit is contained in:
Steve Fink 2020-05-08 16:44:58 +00:00
Родитель 72ce28c40f
Коммит 96e3f93514
2 изменённых файлов: 117 добавлений и 32 удалений

Просмотреть файл

@ -5,6 +5,7 @@
// Global defaults
var gDefaultGarbagePiles = "8M";
var gDefaultGarbagePerFrame = "8K";
var gDefaultTestDuration = 8.0;
function parse_units(v) {
if (!v.length) {
@ -81,6 +82,47 @@ class AllocationLoad {
}
}
class LoadCycle {
constructor(tests_to_run, duration) {
this.queue = [...tests_to_run];
this.duration = duration;
this.idx = -1;
}
get current() {
return this.queue[this.idx];
}
start(now = performance.now()) {
this.idx = 0;
this.cycleStart = this.started = now;
}
tick(now = performance.now()) {
if (this.currentLoadElapsed(now) < this.duration) {
return;
}
this.idx++;
this.started = now;
if (this.idx >= this.queue.length) {
this.idx = -1;
}
}
done() {
return this.idx == -1;
}
cycleElapsed(now = performance.now()) {
return now - this.cycleStart;
}
currentLoadElapsed(now = performance.now()) {
return now - this.started;
}
}
class AllocationLoadManager {
constructor(tests) {
this._loads = new Map();
@ -89,6 +131,17 @@ class AllocationLoadManager {
}
this._active = undefined;
this._paused = false;
this._eventsSinceLastTick = 0;
// Public API
this.cycle = null;
this.testDurationMS = gDefaultTestDuration * 1000;
// Constants
this.CYCLE_STARTED = 1;
this.CYCLE_STOPPED = 2;
this.LOAD_ENDED = 4;
this.LOAD_STARTED = 8;
}
activeLoad() {
@ -132,20 +185,58 @@ class AllocationLoadManager {
}
}
tick() {
tick(now = performance.now()) {
this.lastActive = this._active;
let events = this._eventsSinceLastTick;
this._eventsSinceLastTick = 0;
if (this.cycle) {
const prev = this.cycle.current;
this.cycle.tick(now);
if (this.cycle.current != prev) {
if (this.cycle.current) {
this.setActiveLoadByName(this.cycle.current);
} else {
this.deactivateLoad();
}
events |= this.LOAD_ENDED;
if (this.cycle.done()) {
events |= this.CYCLE_STOPPED;
this.cycle = null;
} else {
events |= this.LOAD_STARTED;
}
}
}
if (this._active && !this._paused) {
this._active.tick();
}
return events;
}
startCycle(tests_to_run, now = performance.now()) {
this.cycle = new LoadCycle(tests_to_run, this.testDurationMS);
this.cycle.start(now);
this.setActiveLoadByName(this.cycle.current);
this._eventsSinceLastTick |= this.CYCLE_STARTED | this.LOAD_STARTED;
}
cycleStopped() {
return !this.cycle || this.cycle.done();
}
cycleCurrentLoadRemaining(now = performance.now()) {
return this.cycleStopped()
? 0
: this.testDurationMS - this.cycle.currentLoadElapsed(now);
}
}
// Current test state.
var gLoadMgr = undefined;
var testDuration = undefined; // ms
var testStart = undefined; // ms
var testQueue = [];
function format_gcBytes(bytes) {
if (bytes < 4000) {
return `${bytes} bytes`;
@ -171,7 +262,7 @@ function compute_test_score(histogram) {
for (let [delay, count] of histogram) {
score += Math.abs((delay - 1000 / 60) * count);
}
score = score / (testDuration / 1000);
score = score / (gLoadMgr.testDurationMS / 1000);
return Math.round(score * 1000) / 1000;
}

Просмотреть файл

@ -431,17 +431,20 @@ function handler(timestamp) {
return;
}
if (testState === "running" && timestamp - testStart > testDuration) {
end_test(timestamp);
const events = gLoadMgr.tick(timestamp);
if (events & gLoadMgr.LOAD_ENDED) {
end_test(timestamp, gLoadMgr.lastActive);
if (!gLoadMgr.cycleStopped()) {
start_test();
}
}
if (testState == "running") {
document.getElementById("test-progress").textContent =
((testDuration - (timestamp - testStart)) / 1000).toFixed(1) + " sec";
(gLoadMgr.cycleCurrentLoadRemaining(timestamp) / 1000).toFixed(1) +
" sec";
}
gLoadMgr.tick();
const delay = gFrameTimer.on_frame_finished(timestamp);
update_histogram(gHistogram, delay);
@ -592,15 +595,9 @@ function run_all_tests() {
function start_test_cycle(tests_to_run) {
// Convert from an iterable to an array for pop.
testQueue = [];
for (var key of tests_to_run) {
testQueue.push(key);
}
gLoadMgr.startCycle(tests_to_run);
testState = "running";
testStart = performance.now();
gHistogram.clear();
start_test(testQueue.shift());
reset_draw_state();
}
@ -615,24 +612,19 @@ function update_load_state_indicator() {
document.getElementById("load-running").textContent = loadState;
}
function start_test(testName) {
change_load(testName);
console.log(`Running test: ${testName}`);
document.getElementById("test-selection").value = testName;
function start_test() {
console.log(`Running test: ${gLoadMgr.activeLoad().name}`);
document.getElementById("test-selection").value = gLoadMgr.activeLoad().name;
update_load_state_indicator();
}
function end_test(timestamp) {
function end_test(timestamp, load) {
document.getElementById("test-progress").textContent = "(not running)";
report_test_result(gLoadMgr.activeLoad(), gHistogram);
report_test_result(load, gHistogram);
gHistogram.clear();
console.log(`Ending test ${gLoadMgr.activeLoad().name}`);
if (testQueue.length) {
start_test(testQueue.shift());
testStart = timestamp;
} else {
console.log(`Ending test ${load.name}`);
if (gLoadMgr.cycleStopped()) {
testState = "idle";
testStart = 0;
}
reset_draw_state();
}
@ -699,8 +691,10 @@ function change_load(new_load_name) {
function duration_changed() {
var durationInput = document.getElementById("test-duration");
testDuration = parseInt(durationInput.value) * 1000;
console.log(`Updated test duration to: ${testDuration / 1000} seconds`);
gLoadMgr.testDurationMS = parseInt(durationInput.value) * 1000;
console.log(
`Updated test duration to: ${gLoadMgr.testDurationMS / 1000} seconds`
);
}
function onLoadChange() {