1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 // This requires a gHost to have been created that provides host-specific
9 // facilities. See eg spidermonkey.js.
11 loadRelativeToScript("argparse.js");
12 loadRelativeToScript("harness.js");
13 loadRelativeToScript("sequencer.js");
14 loadRelativeToScript("scheduler.js");
15 loadRelativeToScript("perf.js");
16 loadRelativeToScript("test_list.js");
18 var gPerf = new PerfTracker();
20 var tests = new Map();
21 foreach_test_file(f => loadRelativeToScript(f));
22 for (const [name, info] of tests.entries()) {
23 if ("enabled" in info && !info.enabled) {
28 function tick(loadMgr, timestamp) {
29 gPerf.before_mutator(timestamp);
31 const events = loadMgr.tick(timestamp);
33 gPerf.after_mutator(timestamp);
37 function run(opts, loads) {
39 for (const mut of loads) {
42 } else if (mut === "all") {
43 sequence.push(...tests.keys());
45 sequence.push(...[...tests.keys()].filter(t => t.includes(mut)));
48 if (loads.length === 0) {
49 sequence.push(...tests.keys());
52 const loadMgr = new AllocationLoadManager(tests);
53 const perf = new FrameHistory(gNumSamples);
55 const mutators = sequence.map(name => new SingleMutatorSequencer(loadMgr.getByName(name), gPerf, opts.duration));
57 if (opts.sequencer == 'cycle') {
58 sequencer = new ChainSequencer(mutators);
59 } else if (opts.sequencer == 'find50') {
60 const seekers = mutators.map(s => new Find50Sequencer(s, loadMgr));
61 sequencer = new ChainSequencer(seekers);
64 const schedulerCtors = {
65 keepup: OptimizeForFrameRate,
66 vsync: VsyncScheduler,
68 const scheduler = new schedulerCtors[opts.sched](gPerf);
72 const t0 = gHost.now();
76 loadMgr.startSequencer(sequencer);
77 print(`${loadMgr.activeLoad().name} starting`);
78 while (loadMgr.load_running()) {
79 const timestamp = gHost.now();
80 const completed = scheduler.tick(loadMgr, timestamp);
81 const after_tick = gHost.now();
83 perf.on_frame(timestamp);
86 print(`${loadMgr.lastActive.name} ended`);
87 if (loadMgr.load_running()) {
88 print(`${loadMgr.activeLoad().name} starting`);
94 possible += (loadMgr.testDurationMS / 1000) * FPS;
95 const elapsed = ((after_tick - t0) / 1000).toFixed(2);
96 print(` observed ${frames} / ${possible} frames in ${elapsed} seconds`);
99 scheduler.wait_for_next_frame(t0, timestamp, after_tick);
103 function report_results() {
104 for (const result of gPerf.results) {
109 mutating_and_gc_fraction,
113 dropped_60fps_frames,
114 dropped_60fps_fraction,
119 const drop_pct = percent(dropped_60fps_fraction);
120 const mut_pct = percent(mutating_and_gc_fraction);
121 const mut_sec = mutating.toFixed(2);
122 const full_sec = full_time.toFixed(2);
123 const susp_sec = suspended.toFixed(2);
125 ${frames} (60fps) frames seen out of expected ${Math.floor(full_time * 60)}
126 ${dropped_60fps_frames} = ${drop_pct} 60fps frames dropped
127 ${mut_pct} of run spent mutating and GCing (${mut_sec}sec out of ${full_sec}sec vs ${susp_sec} sec waiting)
128 ${minorGCs} minor GCs, ${majorGCs} major GCs
133 var argparse = new ArgParser("JS shell microbenchmark runner");
134 argparse.add_argument(["--duration", "-d"], {
135 default: gDefaultTestDuration,
136 help: "how long to run mutators for (in seconds)"
138 argparse.add_argument("--sched", {
140 options: ["keepup", "vsync"],
141 help: "frame scheduler"
143 argparse.add_argument("--sequencer", {
145 options: ["cycle", "find50"],
146 help: "mutator sequencer"