Skip to content

Commit ff5a891

Browse files
committed
Fix pnpm bench on macos
1 parent cf6f6df commit ff5a891

File tree

6 files changed

+86
-14
lines changed

6 files changed

+86
-14
lines changed

bin/benchmark.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ Output directory:
1616
Options:
1717
--force delete cached directories before running
1818
--reuse reuse existing apps and tarballs, if available (by default only the control app/tarball is reused)
19+
--no-headless run Chrome without headless mode (opens visible browser windows)
20+
On macOS, benchmarks will run sequentially (one browser at a time)
1921
2022
Notes:
2123
- This script runs \`pnpm install\` and \`node ./bin/build-for-publishing.js\` in both repos.
@@ -27,11 +29,13 @@ Notes:
2729

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

3134
try {
3235
await runBenchmark({
3336
force: FORCE,
3437
reuse: REUSE,
38+
headless: HEADLESS,
3539
});
3640
} catch (error) {
3741
console.error(error);

bin/benchmark/run.mjs

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ const EXPERIMENT_DIRS = {
6666
repo: REPO_ROOT,
6767
};
6868

69-
export async function runBenchmark({ force = false, reuse = false } = {}) {
69+
export async function runBenchmark({ force = false, reuse = false, headless = true } = {}) {
7070
await ensureDir(BENCH_ROOT);
7171

7272
if (force) {
@@ -119,15 +119,15 @@ export async function runBenchmark({ force = false, reuse = false } = {}) {
119119
});
120120

121121
try {
122-
await bootAndRun();
122+
await bootAndRun({ headless });
123123
} finally {
124124
console.log(`\n\tCleaning up servers with SIGKILL...`);
125125

126126
await killPortProcess([DEFAULT_CONTROL_PORT, DEFAULT_EXPERIMENT_PORT]);
127127
}
128128
}
129129

130-
async function bootAndRun() {
130+
async function bootAndRun({ headless = true } = {}) {
131131
const controlUrl = `http://127.0.0.1:${DEFAULT_CONTROL_PORT}`;
132132
const experimentUrl = `http://127.0.0.1:${DEFAULT_EXPERIMENT_PORT}`;
133133
const markersString = buildMarkersString(DEFAULT_MARKERS);
@@ -164,14 +164,44 @@ async function bootAndRun() {
164164
'--experimentURL',
165165
experimentUrl,
166166
'--report',
167-
'--headless',
168167
'--cpuThrottleRate',
169168
DEFAULT_THROTTLE,
170169
'--markers',
171170
markersString,
172171
'--debug',
173172
'--browserArgs',
174-
`"--incognito,--disable-gpu,--mute-audio,--log-level=3,--headless=new"`,
173+
[
174+
'--no-sandbox',
175+
'--crash-dumps-dir=./tmp',
176+
// Disable task throttling (also in TracerBench defaults, but explicit here for clarity)
177+
'--disable-background-timer-throttling',
178+
'--disable-backgrounding-occluded-windows',
179+
'--disable-renderer-backgrounding',
180+
// Disable caching and unnecessary subsystems
181+
'--disable-dev-shm-usage',
182+
'--disable-cache',
183+
'--disable-v8-idle-tasks',
184+
'--disable-breakpad',
185+
'--disable-component-update',
186+
'--disable-background-networking',
187+
'--disable-notifications',
188+
'--disable-hang-monitor',
189+
'--safebrowsing-disable-auto-update',
190+
'--ignore-certificate-errors',
191+
'--v8-cache-options=none',
192+
// Use the new headless mode to support multiple targets
193+
...(headless ? ['--headless=new'] : []),
194+
// GPU: use software rendering via SwiftShader, but do NOT
195+
// combine --disable-gpu with --use-gl or --disable-software-rasterizer
196+
// as the contradictory flags cause use-after-free crashes on macOS
197+
'--disable-gpu',
198+
'--disable-gpu-compositing',
199+
// Disable Chrome ML/TFLite features (suppresses XNNPACK/TFLite init)
200+
'--disable-features=TranslateUI',
201+
'--disable-features=UseChromiumML',
202+
'--disable-features=UseTfLite',
203+
'--disable-features=TensorFlowLite',
204+
].join(','),
175205
];
176206

177207
await run('node', args, { cwd: EXPERIMENT_DIRS.app });

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,10 @@
166166
"@swc/core",
167167
"core-js",
168168
"esbuild"
169-
]
169+
],
170+
"patchedDependencies": {
171+
"@tracerbench/core@8.0.1": "patches/@tracerbench__core@8.0.1.patch"
172+
}
170173
},
171174
"peerDependencies": {
172175
"@glimmer/component": ">= 1.1.2"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
diff --git a/dist/create-trace-benchmark.js b/dist/create-trace-benchmark.js
2+
index 5918e8f7665b3e796ef88283fc40c2b3286a564f..e1a8768964de8b3c16d38bfb6280d836b45aba0b 100644
3+
--- a/dist/create-trace-benchmark.js
4+
+++ b/dist/create-trace-benchmark.js
5+
@@ -45,9 +45,8 @@ function createTraceBenchmark(group, sampleTrace, options = {}) {
6+
}
7+
exports.default = createTraceBenchmark;
8+
function getCategories(isTrial, options) {
9+
- const categories = ['-*', ...defaultCategories];
10+
+ const categories = [...defaultCategories];
11+
if (isTrial) {
12+
- categories.push(...captureAllDevtoolsTimelineCategories, ...captureCpuProfileCategories, captureCpuProfilesHiresCategory, captureFilmStripCategory, ...capturePaintProfileCategories);
13+
if (options.additionalTrialCategories) {
14+
categories.push(...options.additionalTrialCategories);
15+
}

pnpm-lock.yaml

Lines changed: 7 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

smoke-tests/benchmark-app/app/run-benchmark.js

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,21 @@ export function waitForIdle() {
3333
});
3434
}
3535

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

3752
export function enforcePaintEvent() {
3853
const docElem = document.documentElement;
@@ -64,12 +79,12 @@ async function renderBenchmark() {
6479
let resolveRender
6580

6681
await measureRender('render', 'renderStart', 'renderEnd', () => {
67-
requestIdleCallback(() => {
82+
requestIdleCallback(() => {
6883
if (!resolveRender) return;
6984

7085
resolveRender();
7186
resolveRender = undefined;
72-
});
87+
});
7388

7489
});
7590

@@ -134,25 +149,25 @@ export async function runBenchmark() {
134149
emitDomClickEvent(ButtonSelectors.Clear);
135150
});
136151

137-
await waitForIdle();
152+
await waitForTraceFlush();
138153

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

143-
await waitForIdle();
158+
await waitForTraceFlush();
144159

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

149-
await waitForIdle();
164+
await waitForTraceFlush();
150165

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

155-
await waitForIdle();
170+
await waitForTraceFlush();
156171

157172
await app('clearManyItems2', () => {
158173
emitDomClickEvent(ButtonSelectors.Clear);

0 commit comments

Comments
 (0)