Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions bin/benchmark.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ Output directory:
Options:
--force delete cached directories before running
--reuse reuse existing apps and tarballs, if available (by default only the control app/tarball is reused)
--no-headless run Chrome without headless mode (opens visible browser windows)
On macOS, benchmarks will run sequentially (one browser at a time)

Notes:
- This script runs \`pnpm install\` and \`node ./bin/build-for-publishing.js\` in both repos.
Expand All @@ -27,11 +29,13 @@ Notes:

const FORCE = hasFlag(process.argv, '--force');
const REUSE = hasFlag(process.argv, '--reuse');
const HEADLESS = !hasFlag(process.argv, '--no-headless');

try {
await runBenchmark({
force: FORCE,
reuse: REUSE,
headless: HEADLESS,
});
} catch (error) {
console.error(error);
Expand Down
40 changes: 35 additions & 5 deletions bin/benchmark/run.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const EXPERIMENT_DIRS = {
repo: REPO_ROOT,
};

export async function runBenchmark({ force = false, reuse = false } = {}) {
export async function runBenchmark({ force = false, reuse = false, headless = true } = {}) {
await ensureDir(BENCH_ROOT);

if (force) {
Expand Down Expand Up @@ -119,15 +119,15 @@ export async function runBenchmark({ force = false, reuse = false } = {}) {
});

try {
await bootAndRun();
await bootAndRun({ headless });
} finally {
console.log(`\n\tCleaning up servers with SIGKILL...`);

await killPortProcess([DEFAULT_CONTROL_PORT, DEFAULT_EXPERIMENT_PORT]);
}
}

async function bootAndRun() {
async function bootAndRun({ headless = true } = {}) {
const controlUrl = `http://127.0.0.1:${DEFAULT_CONTROL_PORT}`;
const experimentUrl = `http://127.0.0.1:${DEFAULT_EXPERIMENT_PORT}`;
const markersString = buildMarkersString(DEFAULT_MARKERS);
Expand Down Expand Up @@ -164,14 +164,44 @@ async function bootAndRun() {
'--experimentURL',
experimentUrl,
'--report',
'--headless',
'--cpuThrottleRate',
DEFAULT_THROTTLE,
'--markers',
markersString,
'--debug',
'--browserArgs',
`"--incognito,--disable-gpu,--mute-audio,--log-level=3,--headless=new"`,
[
'--no-sandbox',
'--crash-dumps-dir=./tmp',
// Disable task throttling (also in TracerBench defaults, but explicit here for clarity)
'--disable-background-timer-throttling',
'--disable-backgrounding-occluded-windows',
'--disable-renderer-backgrounding',
// Disable caching and unnecessary subsystems
'--disable-dev-shm-usage',
'--disable-cache',
'--disable-v8-idle-tasks',
'--disable-breakpad',
'--disable-component-update',
'--disable-background-networking',
'--disable-notifications',
'--disable-hang-monitor',
'--safebrowsing-disable-auto-update',
'--ignore-certificate-errors',
'--v8-cache-options=none',
// Use the new headless mode to support multiple targets
...(headless ? ['--headless=new'] : []),
// GPU: use software rendering via SwiftShader, but do NOT
// combine --disable-gpu with --use-gl or --disable-software-rasterizer
// as the contradictory flags cause use-after-free crashes on macOS
'--disable-gpu',
'--disable-gpu-compositing',
// Disable Chrome ML/TFLite features (suppresses XNNPACK/TFLite init)
'--disable-features=TranslateUI',
'--disable-features=UseChromiumML',
'--disable-features=UseTfLite',
'--disable-features=TensorFlowLite',
].join(','),
];

await run('node', args, { cwd: EXPERIMENT_DIRS.app });
Expand Down
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,10 @@
"@swc/core",
"core-js",
"esbuild"
]
],
"patchedDependencies": {
"@tracerbench/core@8.0.1": "patches/@tracerbench__core@8.0.1.patch"
}
},
"peerDependencies": {
"@glimmer/component": ">= 1.1.2"
Expand Down
15 changes: 15 additions & 0 deletions patches/@tracerbench__core@8.0.1.patch
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rn, I'm trying to figure out a better diff here to PR to tracerbench

Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
diff --git a/dist/create-trace-benchmark.js b/dist/create-trace-benchmark.js
index 5918e8f7665b3e796ef88283fc40c2b3286a564f..e1a8768964de8b3c16d38bfb6280d836b45aba0b 100644
--- a/dist/create-trace-benchmark.js
+++ b/dist/create-trace-benchmark.js
@@ -45,9 +45,8 @@ function createTraceBenchmark(group, sampleTrace, options = {}) {
}
exports.default = createTraceBenchmark;
function getCategories(isTrial, options) {
- const categories = ['-*', ...defaultCategories];
+ const categories = [...defaultCategories];
if (isTrial) {
- categories.push(...captureAllDevtoolsTimelineCategories, ...captureCpuProfileCategories, captureCpuProfilesHiresCategory, captureFilmStripCategory, ...capturePaintProfileCategories);
if (options.additionalTrialCategories) {
categories.push(...options.additionalTrialCategories);
}
9 changes: 7 additions & 2 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 21 additions & 6 deletions smoke-tests/benchmark-app/app/run-benchmark.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,21 @@ export function waitForIdle() {
});
}

/**
* After heavy DOM operations (e.g. rendering/clearing 5000 items), Chrome's
* internal trace-writer thread may fall behind. requestIdleCallback only waits
* for the *main* thread to be idle — the trace-writer is a separate thread.
* This explicit delay gives the trace writer time to flush its buffer so that
* subsequent performance.mark() events are not lost to packet drops.
*/
export function waitForTraceFlush() {
return new Promise((resolve) => {
requestIdleCallback(() => {
setTimeout(resolve, 100);
});
});
}


export function enforcePaintEvent() {
const docElem = document.documentElement;
Expand Down Expand Up @@ -64,12 +79,12 @@ async function renderBenchmark() {
let resolveRender

await measureRender('render', 'renderStart', 'renderEnd', () => {
requestIdleCallback(() => {
requestIdleCallback(() => {
if (!resolveRender) return;

resolveRender();
resolveRender = undefined;
});
});

});

Expand Down Expand Up @@ -134,25 +149,25 @@ export async function runBenchmark() {
emitDomClickEvent(ButtonSelectors.Clear);
});

await waitForIdle();
await waitForTraceFlush();

await app('render5000Items1', () => {
emitDomClickEvent(ButtonSelectors.Create5000);
});

await waitForIdle();
await waitForTraceFlush();

await app('clearManyItems1', () => {
emitDomClickEvent(ButtonSelectors.Clear);
});

await waitForIdle();
await waitForTraceFlush();

await app('render5000Items2', () => {
emitDomClickEvent(ButtonSelectors.Create5000);
});

await waitForIdle();
await waitForTraceFlush();

await app('clearManyItems2', () => {
emitDomClickEvent(ButtonSelectors.Clear);
Expand Down