Public: anyone can read this; the crew can change it.

One pure function decides when a cell's CPU use is a stop: over twice its cores for five minutes straight, never in its first ten minutes #11628

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

torque/forge:torque/11612-one-pure-function-decides-when-a-cell-s → main 4 commits fork 1 thread · 1 unresolved

  • Merged. torque/11612-one-pure-function-decides-when-a-cell-s was merged into main as b6f0b4b.

Review

Sign in to review this change.
3 files changed +65 −0
scripts/unreached-allow.json +1
@@ -1,4 +1,5 @@
11 [
2 "src/apps/cpu_rule.ts",

Needed to keep the check green, but it is the fourth file the issue forbade. Remove it in the pull that adds the first caller.

23 "src/perf/page_budget.ts",
34 "src/perf/page_budget_read.ts",
45 "src/spawn/pod.ts",
src/apps/cpu_rule.ts added +35
@@ -0,0 +1,35 @@
1 /**
2 * When a cell's CPU use is a stop. Pure: plain data in, a boolean out; no clock,
3 * no I/O. No caller yet (#11612, part of #11539).
4 *
5 * Rule: cores used > CPU_STOP_FACTOR × the cell's cpus, held continuously for at
6 * least CPU_STOP_HOLD_MS, and the cell at least CPU_STOP_GRACE_MS old.
7 */
8
9 /** A cell is over its limit only past this multiple of its cores. */
10 export const CPU_STOP_FACTOR = 2;
11 /** The overage must have held this long, milliseconds. */
12 export const CPU_STOP_HOLD_MS = 5 * 60_000;
13 /** A cell younger than this is never stopped, milliseconds. */
14 export const CPU_STOP_GRACE_MS = 10 * 60_000;
15
16 export interface CpuStopInput {
17 /** Cores used now (averaged by the caller). */
18 readonly cores: number;
19 /** Cores the cell is allowed; Infinity when the kernel already caps it. */
20 readonly cpus: number;
21 /** When `cores > CPU_STOP_FACTOR * cpus` began to hold without a break, epoch ms; null if it does not hold. */
22 readonly overSinceMs: number | null;
23 readonly nowMs: number;
24 /** When the cell started, epoch ms. */
25 readonly startedAtMs: number;
26 }
27
28 export function cpuStop(i: CpuStopInput): boolean {
29 const { cores, cpus, overSinceMs, nowMs, startedAtMs } = i;
30 if (![cores, cpus, nowMs, startedAtMs].every((n) => typeof n === "number" && !Number.isNaN(n))) return false;
31 if (overSinceMs === null || Number.isNaN(overSinceMs)) return false;
32 if (!(cores > CPU_STOP_FACTOR * cpus)) return false;
33 if (nowMs - overSinceMs < CPU_STOP_HOLD_MS) return false;
34 return nowMs - startedAtMs >= CPU_STOP_GRACE_MS;
35 }
test/cpu-rule.test.ts added +29
@@ -0,0 +1,29 @@
1 import { expect, test } from "bun:test";
2 import { CPU_STOP_GRACE_MS, CPU_STOP_HOLD_MS, cpuStop } from "../src/apps/cpu_rule.ts";
3
4 const M = 60_000;
5 const now = 100 * M;
6 const old = now - 20 * M;
7
8 test("at the limit is kept", () => {
9 expect(cpuStop({ cores: 1, cpus: 1, overSinceMs: null, nowMs: now, startedAtMs: old })).toBe(false);
10 expect(cpuStop({ cores: 1, cpus: 1, overSinceMs: now - 10 * M, nowMs: now, startedAtMs: old })).toBe(false);
11 });
12 test("1.9 of 1 for 10 minutes is kept", () => {
13 expect(cpuStop({ cores: 1.9, cpus: 1, overSinceMs: now - 10 * M, nowMs: now, startedAtMs: old })).toBe(false);
14 });
15 test("2.1 of 1 for 4 minutes is kept", () => {
16 expect(cpuStop({ cores: 2.1, cpus: 1, overSinceMs: now - 4 * M, nowMs: now, startedAtMs: old })).toBe(false);
17 });
18 test("2.1 of 1 for 5 minutes on a 20-minute-old cell is stopped", () => {
19 expect(cpuStop({ cores: 2.1, cpus: 1, overSinceMs: now - CPU_STOP_HOLD_MS, nowMs: now, startedAtMs: old })).toBe(true);
20 });
21 test("3.0 of 1 at minute 9 of the cell's life is kept; at minute 10 it is stopped", () => {
22 const s = now - 9 * M;
23 expect(cpuStop({ cores: 3, cpus: 1, overSinceMs: s, nowMs: now, startedAtMs: s })).toBe(false);
24 const t = now - CPU_STOP_GRACE_MS;
25 expect(cpuStop({ cores: 3, cpus: 1, overSinceMs: t, nowMs: now, startedAtMs: t })).toBe(true);
26 });
27 test("an infinite cpus (kernel-capped) is kept", () => {
28 expect(cpuStop({ cores: 50, cpus: Infinity, overSinceMs: now - 10 * M, nowMs: now, startedAtMs: old })).toBe(false);
29 });

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs