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

A small pod keeps room for the forge: a cell gets the pod's memory less the forge's own #12354

Merged opened this

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

Merged

torque/forge:torque/12346-a-small-pod-keeps-room-for-the-forge-a-c → main 1 commit fork

  • Merged. torque/12346-a-small-pod-keeps-room-for-the-forge-a-c was merged into main as b070674.

Review

Sign in to review this change.
2 files changed +22 −2
src/apps/contain.ts +15 −2
@@ -122,6 +122,19 @@ export const POD_MEMORY_FILE = "/sys/fs/cgroup/memory.max";
122122 /** The share of the pod's memory a single cell may be given. */
123123 export const POD_MEMORY_SHARE = 0.75;
124124
125 /**
126 * What the forge itself needs inside its pod, MiB, measured at about 170 at
127 * rest and 200 under a first hour's work (#12092): a cell is never given the
128 * pod's memory down to this, so on a small machine the check dies, not the forge.
129 */
130 export const FORGE_OWN_MIB = 192;
131
132 /** A share of the pod's bytes for one cell, never more than the pod less the forge's own room. */
133 export function podShareMiB(bytes: number): number {
134 const mib = bytes / 1048576;
135 return Math.max(1, Math.floor(Math.min(mib * POD_MEMORY_SHARE, mib - FORGE_OWN_MIB)));
136 }
137
125138 /**
126139 * The most memory one cell gets, MiB: `FORGE_CELL_MEMORY_MAX_MIB` when set,
127140 * else a share of the pod's own `memory.max`, else 4096 where the host
@@ -165,7 +178,7 @@ function machineCeiling(
165178 try {
166179 const bytes = Number(readFileSync(podFile, "utf8").trim());
167180 if (Number.isFinite(bytes) && bytes > 0)
168 return { mib: Math.max(1, Math.floor((bytes * POD_MEMORY_SHARE) / 1048576)), from: "pod" };
181 return { mib: podShareMiB(bytes), from: "pod" };
169182 } catch {
170183 // no cgroup v2 here, or "max" (unlimited): the fixed default below
171184 }
@@ -191,7 +204,7 @@ function ceilingText(from: CeilingFrom | undefined): string {
191204 : from === "size"
192205 ? `${OWN_SIZE_SHARE * 100}% of this child forge's own size`
193206 : from === "pod"
194 ? `${POD_MEMORY_SHARE * 100}% of the pod's memory.max`
207 ? `${POD_MEMORY_SHARE * 100}% of the pod's memory.max, less the forge's own ${FORGE_OWN_MIB} MiB`
195208 : "the 4096 MiB default, the host states no memory limit";
196209 }
197210
test/memory-ceiling.test.ts +7
@@ -19,6 +19,13 @@ describe("the memory ceiling is never a silent clamp (#3128)", () => {
1919 expect(memoryCeiling(undefined, "/nonexistent/memory.max")).toBe(4096);
2020 });
2121
22 test("a small pod leaves the forge its own room: the check dies, not the forge (#12346)", () => {
23 expect(memoryCeiling(undefined, pod(String(384 * 1048576)))).toBe(192);
24 expect(memoryCeiling(undefined, pod(String(512 * 1048576)))).toBe(320);
25 expect(memoryCeiling(undefined, pod(String(256 * 1048576)))).toBe(64);
26 expect(memoryCeiling(undefined, pod(String(2048 * 1048576)))).toBe(1536);
27 });
28
2229 test("a declared memory above the ceiling produces a warning; within it, none", () => {
2330 const saved = process.env["FORGE_CELL_MEMORY_MAX_MIB"];
2431 process.env["FORGE_CELL_MEMORY_MAX_MIB"] = "4096";

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs