chadtmiller.com/knotless
git that lives in your Atmosphere account
1
10
Coverage builds as many crates at once as a run's CPUs and memory allow
deploy/runner-host/README.md+8−3
| @@ -164,7 +164,7 @@ on the main host, where the deploy's key is. In `deploy/local.env`: | ||
```sh | ||
KNOTLESS_RUNNER_ARGS="--queue --pulls-only chadtmiller.com/knotless --unmetered did:plc:bcgltzqazw5tb6k2g3ttenbj --trust did:plc:bcgltzqazw5tb6k2g3ttenbj --pull-jobs 2" | ||
KNOTLESS_RUNNER_JOBS=2 | ||
KNOTLESS_RUNNER_MEMORY=6 | ||
KNOTLESS_RUNNER_MEMORY=7 | ||
KNOTLESS_RUNNER_CPUS=4 | ||
``` | ||
| ||
| @@ -180,8 +180,13 @@ against no allowance and may take every job, past `--owner-jobs`. | ||
everything is a pull. Its `test` workflow builds every test binary with | ||
coverage and starts PDSes, which takes more than the default 3 GiB a run: | ||
past it the sandbox is killed (`containerManager.WaitPID failed: EOF` in | ||
the log, an OOM kill of `gvisor_sentry` in `dmesg`). So two jobs of 6 GiB and 4 CPUs | ||
each, on an 8-core, 16 GB host, rather than four that each fail. knotless names this runner's account among its | ||
the log, an OOM kill of `gvisor_sentry` in `dmesg`). So two jobs of 7 GiB and 4 CPUs | ||
each, on an 8-core, 16 GB host, rather than four that each fail. Within | ||
them, cargo would still start a rustc for each of the host's 8 cores, and | ||
knotless-serve's takes near 3 GiB under coverage: `harness/cov.mjs` builds | ||
as many crates at once as the cgroup's CPUs, and one for each 2.5 GiB of | ||
its memory at most, so 2 here (`rustc` killed by `oom-killer` in `dmesg` | ||
is this, past those). knotless names this runner's account among its | ||
`runners` (`knotless runners knotless://chadtmiller.com/knotless add | ||
runner.knotless.dev`), so its pulls' checks show. The main host's runner | ||
takes `--queue` without `--pulls` (`KNOTLESS_RUN_ARGS` in | ||
harness/cov.mjs+28−0
| @@ -110,6 +110,34 @@ const shown = spawnSync('rustup', [...cargo, 'llvm-cov', 'show-env', '--sh'], { | ||
const env = { ...process.env, CARGO_TARGET_DIR: target } | ||
for (const [, k, v] of shown.stdout.matchAll(/^export ([A-Z_0-9]+)=(.*)$/gm)) env[k] = v.replace(/^'(.*)'$/, '$1') | ||
| ||
// cargo builds as many crates at once as the host has cores, even in a | ||
// container held to fewer CPUs and less memory than the host has, as a | ||
// runner's --cpus and --memory hold it: on an 8-core host, in 4 CPUs and | ||
// 7 GiB, eight rustc at once, knotless-serve's near 3 GiB among them, | ||
// were killed for memory. So where the cgroup limits it, the build takes | ||
// as many at once as the CPUs it is given, and one for each 2.5 GiB at | ||
// most. CARGO_BUILD_JOBS, set, is kept. | ||
const cgroup = (file) => { | ||
try { | ||
return readFileSync(join('/sys/fs/cgroup', file), 'utf8').trim() | ||
} catch { | ||
return 'max' | ||
} | ||
} | ||
const buildJobs = () => { | ||
const [quota, period] = cgroup('cpu.max').split(' ') | ||
const memory = cgroup('memory.max') | ||
const caps = [] | ||
if (quota !== 'max') caps.push(Math.floor(Number(quota) / Number(period))) | ||
if (memory !== 'max') caps.push(Math.floor(Number(memory) / (2.5 * 2 ** 30))) | ||
return caps.length ? Math.max(1, Math.min(...caps)) : undefined | ||
} | ||
const limited = buildJobs() | ||
if (!env.CARGO_BUILD_JOBS && limited) { | ||
env.CARGO_BUILD_JOBS = String(limited) | ||
console.log(`cov: building ${env.CARGO_BUILD_JOBS} crates at once, as the cgroup's CPUs and memory allow`) | ||
} | ||
| ||
// The tools beside the toolchain's rustc: llvm-size and llvm-profdata. | ||
const rustc = (...args) => execFileSync('rustup', ['run', toolchain, 'rustc', ...args], { encoding: 'utf8' }) | ||
const host = rustc('-vV').match(/^host: (.*)$/m)[1] | ||