Skip to content

Commit c1862c6

Browse files
committed
perf(fmt): prioritize Markdown worker tasks
1 parent a5dbe91 commit c1862c6

3 files changed

Lines changed: 44 additions & 3 deletions

File tree

‎packages/rstack/src/fmt/runner.ts‎

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,17 @@ interface FmtWorkerPoolResult {
1616
processedFileCount: number;
1717
}
1818

19+
/** Benchmarks show stable scheduling gains only when at least eight workers share the queue. */
20+
const minPriorityWorkers = 8;
21+
22+
/**
23+
* Markdown parsing is consistently slower in representative repositories. Keep this signal
24+
* narrow: parser overrides and file size can outweigh the extension, and deferring every JS/TS
25+
* file could turn a large source file into the final straggler.
26+
*/
27+
const isMarkdown = (file: FmtFileRequest): boolean =>
28+
file.path.endsWith('.md') || file.path.endsWith('.mdx');
29+
1930
/** Converts a formatter outcome into the shared per-file result. */
2031
const runFmtFile = async (
2132
file: FmtFileRequest,
@@ -41,6 +52,30 @@ const runFmtFile = async (
4152
}
4253
};
4354

55+
/** Starts slower Markdown parsers first while preserving order within both priority groups. */
56+
const runPriorityFmtFiles = async (
57+
files: FmtFileRequest[],
58+
shouldWrite: boolean,
59+
formatFile: FormatFile,
60+
): Promise<FmtFileOutcome[]> => {
61+
const priority: number[] = [];
62+
const rest: number[] = [];
63+
64+
for (let index = 0; index < files.length; index++) {
65+
(isMarkdown(files[index]) ? priority : rest).push(index);
66+
}
67+
68+
const order = priority.concat(rest);
69+
const outcomes = await Promise.all(
70+
order.map((index) => runFmtFile(files[index], shouldWrite, formatFile)),
71+
);
72+
const results = new Array<FmtFileOutcome>(files.length);
73+
for (let index = 0; index < order.length; index++) {
74+
results[order[index]] = outcomes[index];
75+
}
76+
return results;
77+
};
78+
4479
/** Processes files in a worker pool while preserving input order. */
4580
const runFmtFilesInWorkerPool = async (
4681
files: FmtFileRequest[],
@@ -51,9 +86,12 @@ const runFmtFilesInWorkerPool = async (
5186
const workerPool = await createFmtWorkerPool(files.length, maxWorkers);
5287

5388
try {
54-
const results = await Promise.all(
55-
files.map((file) => runFmtFile(file, shouldWrite, workerPool.formatFile)),
56-
);
89+
const results =
90+
workerPool.workerCount >= minPriorityWorkers
91+
? await runPriorityFmtFiles(files, shouldWrite, workerPool.formatFile)
92+
: await Promise.all(
93+
files.map((file) => runFmtFile(file, shouldWrite, workerPool.formatFile)),
94+
);
5795
const processedFiles: FmtFileResult[] = [];
5896
let processedFileCount = 0;
5997

‎packages/rstack/src/fmt/workerPool.ts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { FmtFileRequest } from './types.ts';
77
type FmtWorkerMethods = typeof import('./worker.ts');
88

99
interface FmtWorkerPool {
10+
readonly workerCount: number;
1011
formatFile: (
1112
file: FmtFileRequest,
1213
shouldWrite: boolean,
@@ -55,6 +56,7 @@ const createFmtWorkerPool = async (
5556
}
5657

5758
return {
59+
workerCount,
5860
formatFile: (file, shouldWrite) => pool.run({ file, shouldWrite }, { name: 'formatFile' }),
5961
terminate: () => pool.destroy(),
6062
};

‎packages/rstack/tests/fmt/runnerWriteFailure.test.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const mocks = rs.hoisted(() => ({
88
rs.mock('../../src/fmt/workerPool.ts', () => ({
99
createFmtWorkerPool: () =>
1010
Promise.resolve({
11+
workerCount: 1,
1112
formatFile: () => Promise.reject(new Error('file write failed')),
1213
terminate: () => {
1314
mocks.terminateCalls++;

0 commit comments

Comments
 (0)