Skip to content

Commit 2f2ee14

Browse files
committed
[ci] Add size-balanced test sequencer for better shard distribution
Jest's default test sequencer sorts alphabetically, causing large test files (eg ReactDOMFloat-test.js at 9k lines, ReactHooksWithNoopRenderer-test.js at 4k lines) to cluster in shard 3/5. This made shard 3/5 average 117s vs 77s for other shards, a 52% slowdown. I'm using filesize as a rough proxy for number of tests. This custom sequencer sorts tests by file size and distributes large files evenly across all shards instead of clustering them together.
1 parent f543655 commit 2f2ee14

2 files changed

Lines changed: 24 additions & 0 deletions

File tree

scripts/jest/config.base.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
module.exports = {
44
globalSetup: require.resolve('./setupGlobal.js'),
5+
testSequencer: require.resolve('./sizeBalancedSequencer.js'),
56
modulePathIgnorePatterns: [
67
'<rootDir>/scripts/rollup/shims/',
78
'<rootDir>/scripts/bench/',
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
'use strict';
2+
3+
const Sequencer = require('@jest/test-sequencer').default;
4+
const fs = require('fs');
5+
6+
class SizeBalancedSequencer extends Sequencer {
7+
shard(tests, {shardIndex, shardCount}) {
8+
const shards = Array.from({length: shardCount}, () => ({tests: [], size: 0}));
9+
const sorted = [...tests].sort((a, b) => fs.statSync(b.path).size - fs.statSync(a.path).size);
10+
11+
for (let i = 0; i < sorted.length; i++) {
12+
const test = sorted[i];
13+
const size = fs.statSync(test.path).size;
14+
const smallest = shards.reduce((min, s) => (s.size < min.size ? s : min));
15+
smallest.tests.push(test);
16+
smallest.size += size;
17+
}
18+
19+
return shards[shardIndex - 1].tests;
20+
}
21+
}
22+
23+
module.exports = SizeBalancedSequencer;

0 commit comments

Comments
 (0)