fix: bound test shard size independently of concurrency
Remove the 32-shard cap so growing inventories do not overfill fixed timeout windows. Keep serial Runtime/Worker/Server shards at most 36 cases and default top-level concurrency at most eight, with explicit --jobs overrides retained. No test exclusions or timeout increases. Validated the complete Server inventory through the normal runner helpers: 1724 passed, 4 existing ignored, no failures or timeouts; 50 suites including doctests, 580 seconds execution. Runner and naming checks: 26 passed. Root cargo check and formatting/diff checks passed.
This commit is contained in:
@@ -53,7 +53,7 @@
|
|||||||
|
|
||||||
### runner:選択の帳簿と実行引数を照合する
|
### runner:選択の帳簿と実行引数を照合する
|
||||||
|
|
||||||
`tools/test.test.ts` の `round-robin shards retain every listed name exactly once at thresholds and the 32-shard cap` は本番parser/sharderへ実形式のlistingを入力し、全名の一意分配と `task.args.slice(3) === selectedNames`、exact/thread/ignore flagsをassertする。`runtime listing persists complete name inventory for large and small binaries` はDeno子でlibtest listingを代替し、本番discovery/executeの保存inventoryを再読取りする。実Rust libtest全体の実行結果照合ではない。
|
`tools/test.test.ts` の `round-robin shards retain every listed name without exceeding the case budget` は本番parser/sharderへ実形式のlistingを入力し、全名の一意分配、分割後のケース数上限と `task.args.slice(3) === selectedNames`、exact/thread/ignore flagsをassertする。`runtime listing persists complete name inventory for large and small binaries` はDeno子でlibtest listingを代替し、本番discovery/executeの保存inventoryを再読取りする。実Rust libtest全体の実行結果照合ではない。
|
||||||
|
|
||||||
`execute preserves live stdout/stderr and times out a group containing a grandchild`、`execute escalates SIGTERM to SIGKILL and reaps a stubborn direct child`、`parent SIGINT/SIGTERM cleans up active groups, reaps children and does not spawn queued commands` は実隔離子プロセスを起動し、PID消滅・保存result・非起動のqueued PIDを観測する。fixtureに独立watchdogがあり、finallyでも回収する。同process group外へ自ら離脱した子孫は対象外。局所入力表を重いrunner全体起動へ移さない。
|
`execute preserves live stdout/stderr and times out a group containing a grandchild`、`execute escalates SIGTERM to SIGKILL and reaps a stubborn direct child`、`parent SIGINT/SIGTERM cleans up active groups, reaps children and does not spawn queued commands` は実隔離子プロセスを起動し、PID消滅・保存result・非起動のqueued PIDを観測する。fixtureに独立watchdogがあり、finallyでも回収する。同process group外へ自ら離脱した子孫は対象外。局所入力表を重いrunner全体起動へ移さない。
|
||||||
|
|
||||||
|
|||||||
+9
-7
@@ -106,9 +106,9 @@ function assertThrows(fn: () => unknown) {
|
|||||||
assert(failed, "expected failure");
|
assert(failed, "expected failure");
|
||||||
}
|
}
|
||||||
|
|
||||||
Deno.test("CPU-derived jobs accommodates concurrent suites within the CLI bound", () => {
|
Deno.test("default jobs bound suite pressure independently of explicit CLI concurrency", () => {
|
||||||
assert(defaultJobs(24) === 32);
|
assert(defaultJobs(24) === 8);
|
||||||
assert(defaultJobs(128) === 32);
|
assert(defaultJobs(128) === 8);
|
||||||
assert(defaultJobs(6) === 8);
|
assert(defaultJobs(6) === 8);
|
||||||
assert(defaultJobs(1) === 2);
|
assert(defaultJobs(1) === 2);
|
||||||
assert(parseJobs([]) === defaultJobs());
|
assert(parseJobs([]) === defaultJobs());
|
||||||
@@ -153,7 +153,7 @@ function listedNames(count: number) {
|
|||||||
return Array.from({ length: count }, (_, i) => `unit::case_${i}`);
|
return Array.from({ length: count }, (_, i) => `unit::case_${i}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
Deno.test("round-robin shards retain every listed name exactly once at thresholds and the 32-shard cap", () => {
|
Deno.test("round-robin shards retain every listed name without exceeding the case budget", () => {
|
||||||
const task = {
|
const task = {
|
||||||
name: "pkg/binary",
|
name: "pkg/binary",
|
||||||
command: "/test-binary",
|
command: "/test-binary",
|
||||||
@@ -178,9 +178,10 @@ Deno.test("round-robin shards retain every listed name exactly once at threshold
|
|||||||
"small binaries must be unchanged",
|
"small binaries must be unchanged",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
const expected = Math.min(32, Math.ceil(count / 36));
|
const expected = Math.ceil(count / 36);
|
||||||
assert(shards.length === expected);
|
assert(shards.length === expected);
|
||||||
const lengths = shards.map((shard) => shard.selectedNames.length);
|
const lengths = shards.map((shard) => shard.selectedNames.length);
|
||||||
|
assert(Math.max(...lengths) <= 36);
|
||||||
assert(Math.max(...lengths) - Math.min(...lengths) <= 1);
|
assert(Math.max(...lengths) - Math.min(...lengths) <= 1);
|
||||||
shards.forEach((shard, index) => {
|
shards.forEach((shard, index) => {
|
||||||
assert(
|
assert(
|
||||||
@@ -212,7 +213,7 @@ Deno.test("global runtime-path packages serialize every normal target without lo
|
|||||||
args: [],
|
args: [],
|
||||||
cwd: "/pkg",
|
cwd: "/pkg",
|
||||||
};
|
};
|
||||||
for (const count of [0, 1, 59, 72, 73, 1135]) {
|
for (const count of [0, 1, 36, 37, 59, 72, 73, 1135, 1716, 2000]) {
|
||||||
const names = listedNames(count);
|
const names = listedNames(count);
|
||||||
const shards = shardRustCommand(task, names);
|
const shards = shardRustCommand(task, names);
|
||||||
assert(
|
assert(
|
||||||
@@ -222,7 +223,8 @@ Deno.test("global runtime-path packages serialize every normal target without lo
|
|||||||
for (const shard of shards) {
|
for (const shard of shards) {
|
||||||
const args = shard.task.args;
|
const args = shard.task.args;
|
||||||
assert(args[args.indexOf("--test-threads") + 1] === "1");
|
assert(args[args.indexOf("--test-threads") + 1] === "1");
|
||||||
if (count > 72) {
|
assert(shard.selectedNames.length <= 36);
|
||||||
|
if (count > 36) {
|
||||||
assert(args[0] === "--exact");
|
assert(args[0] === "--exact");
|
||||||
assert(args.slice(3).join() === shard.selectedNames.join());
|
assert(args.slice(3).join() === shard.selectedNames.join());
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+8
-5
@@ -12,9 +12,10 @@ export const BUILD_TIMEOUT_MS = 1_800_000;
|
|||||||
export const MAX_JOBS = 64;
|
export const MAX_JOBS = 64;
|
||||||
|
|
||||||
export function defaultJobs(cpus = availableParallelism()): number {
|
export function defaultJobs(cpus = availableParallelism()): number {
|
||||||
// Leave headroom for internal runners; higher top-level counts can be chosen
|
// Each suite can spawn its own Runtime, database executors and compiler work.
|
||||||
// explicitly, but are not assumed to improve throughput or timing stability.
|
// CPU count alone over-admits these suites and consumes their timeout budgets.
|
||||||
return Math.min(32, Math.max(1, Math.ceil(cpus * 4 / 3)));
|
// Keep headroom by default; --jobs remains an explicit concurrency override.
|
||||||
|
return Math.min(8, Math.max(1, Math.ceil(cpus * 4 / 3)));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseJobs(args: string[]): number {
|
export function parseJobs(args: string[]): number {
|
||||||
@@ -71,7 +72,7 @@ export function shardRustCommand(
|
|||||||
const serial = ["worker", "worker-runtime", "yoi-workspace-server"].includes(
|
const serial = ["worker", "worker-runtime", "yoi-workspace-server"].includes(
|
||||||
task.name.split("/")[0],
|
task.name.split("/")[0],
|
||||||
);
|
);
|
||||||
if (names.length <= 72) {
|
if (names.length <= (serial ? 36 : 72)) {
|
||||||
return [{
|
return [{
|
||||||
task: serial
|
task: serial
|
||||||
? { ...task, args: [...task.args, "--test-threads", "1"] }
|
? { ...task, args: [...task.args, "--test-threads", "1"] }
|
||||||
@@ -79,7 +80,9 @@ export function shardRustCommand(
|
|||||||
selectedNames: [...names],
|
selectedNames: [...names],
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
const count = Math.min(32, Math.ceil(names.length / 36));
|
// Shard size and concurrency are independent: a growing test inventory must
|
||||||
|
// not silently pack more serial cases into the same fixed timeout window.
|
||||||
|
const count = Math.ceil(names.length / 36);
|
||||||
const shards: string[][] = Array.from({ length: count }, () => []);
|
const shards: string[][] = Array.from({ length: count }, () => []);
|
||||||
names.forEach((name, index) => shards[index % count].push(name));
|
names.forEach((name, index) => shards[index % count].push(name));
|
||||||
return shards.map((selectedNames, index) => ({
|
return shards.map((selectedNames, index) => ({
|
||||||
|
|||||||
Reference in New Issue
Block a user