mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
docs(coverage): record why two-core Tier A runs stay serial (#1741)
* docs(coverage): record why two-core Tier A runs stay serial Answers two review notes on the concurrent Tier A runner with measurements instead of code changes: - Two cores stay serial. Two in flight would give each project one Jest worker, which runs Jest in-band; on a 2-core / 7 GB container ui-playback and web ran out of their 2 GiB default heap. With a 4 GiB heap it passed about 15% faster on a warm cache for 1.2 GiB more peak memory. CI runs on 4 cores. A test pins that the defaults never drop to one worker. - Per-project output buffering is bounded in practice: a big project with every test failing printed 1.8 MB while its Jest process peaked at 850 MB. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs(coverage): say two-core runs keep two workers per project Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: 4gray <fourgray@proton.me> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
4 files changed
+24
-2
No files matched your search
@@ -61,6 +61,13 @@ export function orderLongestFirst(projects, weightOf) {
|
||||
* How many projects to keep in flight. Defaults to one less than the core
|
||||
* count, capped at three: beyond that the per-process start-up cost is paid
|
||||
* anyway and the Jest workers of the concurrent runs starve each other.
|
||||
*
|
||||
* Two cores stay serial on purpose. Two in flight there would leave each
|
||||
* project one worker, and Jest then runs in-band: every spec file of a big
|
||||
* project (ui-playback, web) shares one heap. On a 2-core / 7 GB box, where
|
||||
* Node's default heap is 2 GiB, that heap ran out; with a 4 GiB heap it
|
||||
* passed, about 15% faster than serial on a warm cache but with 1.2 GiB more
|
||||
* peak memory. CI runs on 4 cores, so the saving would not reach it.
|
||||
*/
|
||||
export function resolveConcurrency({ requested, cpuCount }) {
|
||||
if (Number.isInteger(requested) && requested > 0) return requested;
|
||||
@@ -70,7 +77,8 @@ export function resolveConcurrency({ requested, cpuCount }) {
|
||||
/**
|
||||
* Jest workers per project, so that concurrency × workers stays near the core
|
||||
* count. Small projects never use them all, which is what leaves room for the
|
||||
* other slots.
|
||||
* other slots. The defaults never go below two on a multi-core machine:
|
||||
* `--max-workers=1` runs Jest in-band (see resolveConcurrency).
|
||||
*/
|
||||
export function resolveWorkersPerProject({ requested, concurrency, cpuCount }) {
|
||||
if (Number.isInteger(requested) && requested > 0) return requested;
|
||||
|
||||
@@ -83,6 +83,14 @@ test('derives concurrency and workers from the core count unless overridden', ()
|
||||
assert.equal(resolveWorkersPerProject({ requested: 1, concurrency: 3, cpuCount: 16 }), 1);
|
||||
});
|
||||
|
||||
test('defaults never leave a project one in-band Jest worker on a multi-core machine', () => {
|
||||
for (let cpuCount = 2; cpuCount <= 64; cpuCount += 1) {
|
||||
const concurrency = resolveConcurrency({ requested: undefined, cpuCount });
|
||||
const workers = resolveWorkersPerProject({ requested: undefined, concurrency, cpuCount });
|
||||
assert.ok(workers >= 2, `${cpuCount} cores: ${concurrency} in flight × ${workers} worker`);
|
||||
}
|
||||
});
|
||||
|
||||
function task(name, { delay = 0, status = 0, log }) {
|
||||
return {
|
||||
name,
|
||||
|
||||
@@ -161,6 +161,9 @@ function buildNxArgs(project) {
|
||||
* Output is buffered per project and written in one piece when the project
|
||||
* finishes: with several Jest processes in flight, interleaved lines would be
|
||||
* unreadable and the coverage-failure scanner would see other projects' text.
|
||||
* Holding it in memory is cheap: a finished project's block is released, fail-
|
||||
* fast starts nothing new, and a big project with every test failing printed
|
||||
* 1.8 MB while its Jest process peaked at 850 MB.
|
||||
*/
|
||||
function spawnCoverage(args, scanner, output) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
Reference in new issue
Block a user