Skip to content

pgw#1137 (§4.30, pgw#1127 item 6): a mint on the USER'S machine is polite — declared, not toggled - #655

Merged
PaulFidika merged 1 commit into
masterfrom
1137-compile-politeness
Aug 11, 2026
Merged

pgw#1137 (§4.30, pgw#1127 item 6): a mint on the USER'S machine is polite — declared, not toggled#655
PaulFidika merged 1 commit into
masterfrom
1137-compile-politeness

Conversation

@PaulFidika

Copy link
Copy Markdown
Contributor

Closes pgw#1127 §7 item 6 (filed, unowned) and discharges DESIGN-RULINGS §4.30's "be nice, especially on cozy-local — never saturate the user's only machine."

What cozy-local does today (before this PR)

cli/run.py:872local_serve.enable_compiledmint_delegate.build_cellmint_process.runmint_child. Since b29a5e95 that is the REAL mint chain on a desktop, and:

  • Nothing niced. os.nice appears nowhere in src/ (pgw#1127 §6).
  • SERVING_HEADROOM_CPUS = 2 (aot_compile_pool.py:132) is sized for "an asyncio beat and an eager forward", i.e. a pod's tenant. On a 32-core desktop that leaves cpu_workers = 15.
  • MAX_ENTRY_WORKERS = 8 (:171) bounds inductor-cache write amplification and concurrent cc1plus "on a box whose disk the serving process also uses" — here that disk is the user's.
  • ENTRY_RSS_RESERVE_BYTES = 4 GiB (:196) protects a tenant request from the OOM killer; MemAvailable counts the user's page cache as free.
  • compile_threads is NOT torch's 32 hereaot_mint.MINT_COMPILE_THREADS = 4 is set as a default at aot_mint.py:805. Genuinely chosen, and left alone.
  • K is 1 anyway today: aot_mint.py:2187-2204 forces parallel=False for a weight-free mint, and since pgw#1080 every production mint is weight-free. So the compile runs IN the mint child — which is why nicing the pool's spawns (the parked 1111-mint-parallelism-restore approach) would nice a path that does not currently run.
  • A closed terminal orphans the compile. mint_process.py:750 spawns start_new_session=True, and mint_child armed no PR_SET_PDEATHSIG.

The design

compile_posture.CompilePosture — one fact, declared by the entry that knows (local_serve is the only site in the tree that says USER_MACHINE), riding MintRequest as a typed field beside vram_cap_bytes. Not an env var (§1.17: an env may carry a VALUE, not a DECISION). Not derived from local_cell_store.trust_class() or publisher is None — both are facts about the SINK, and a rented community-cloud pod matches both while having nobody sitting at it; nor from worker_goals, which says what a pod was bought to do. All three proxies are fenced by a test, because pgw#1127 §2's own warning is "two derivations of one fact".

term fleet user machine why
nice 0 19 the only lever that preserves interactivity — a core reservation does not stop the scheduler putting a compile on the core the compositor wants. Also free: a niced mint uses the whole idle machine and yields the instant the user returns.
core budget vcpus - 2 min(vcpus - 2, vcpus/2) CPUS_PER_ENTRY_WORKER=2 is an AVERAGE; at the burst a pod asks for ~2x the box, correct when the box is ours. Halving makes the burst ask for the machine, not double it. 4-core laptop → K=1; 32-core workstation → 8 by cores, 4 by ceiling.
entry ceiling 8 4 nice does nothing for K concurrent cc1plus, K inductor caches, K page-cache working sets — and that disk is the user's.
host RAM reserve 4 GiB 8 GiB a mint that OOMs a desktop is worse than a slow one; MemAvailable reports the user's page cache as free.

Rejected, with reasons (in the module docstring): an interactivity probe — cross-platform mess, and wrong in the case that matters, since a developer running a build in a terminal generates no input events; nice already IS the yield. ionice — no stdlib wrapper, and a no-op on the none/mq-deadline schedulers desktops ship; the RAM reserve and entry ceiling bound the I/O by bounding the writers. A third posture for community cloud — untrusted hardware rented by the second with nobody on it compiles as FLEET, deliberately.

Nice is applied by the CHILD to itself, never through preexec_fnarm_parent_death_signal's docstring already writes down the hazard (a preexec_fn forces fork() over posix_spawn() for a process with live gRPC threads and pthread_atfork handlers). An AST fence keeps it that way; it is also the coordination point with the parked pgw#1111 lane, whose WIP took the preexec_fn route.

What a user now sees

cozy: compiling sdxl for this machine — this happens ONCE; every later run of this
      endpoint arms from ~/.cache/cozy/compile-cells with no compile and no network.
      It takes a while.
      This is your machine, so the compile is polite: lowest CPU priority (nice 19),
      at most 4 parallel worker(s) sized against 16 of your 32 cores, and 8 GiB of
      RAM left alone.
      Ctrl-C is safe — finished work is kept and the next run picks up where this
      one stopped.
cozy: [sdxl] compile_entries 7/18 — 4m12s elapsed
cozy: compiled sdxl in 21m04s — kept at ~/.cache/cozy/compile-cells; later runs arm from it.

The frames still reach the hub activity unchanged; the terminal watcher is an additional sink a fleet mint never passes.

Interruptibility

The mint child arms PR_SET_PDEATHSIG on a user machine, so a closed terminal no longer leaves a detached full-speed compile tree. Nothing is wasted: aot_resume's cross-attempt bank is already sited outside the per-attempt workdir (mint_delegate.py:312), and a test pins that — otherwise "Ctrl-C is safe" becomes a lie.

The pod does not regress

FLEET is the struct default everywhere, so no fleet caller changed. test_a_POD_width_is_arithmetically_unchanged_by_this_issue compares every bound against an independent re-implementation of the pre-issue formula over six pod shapes (modest pod, fat H100, widest pod, CPU-only cell, operator-forced narrow, RAM-bound small) — a non-regression test that asked the new code whether it changed could only answer no.

RED-first

The file is a collection error on origin/master (36/36), and each behavioural claim is additionally mutation-proven individually on this branch:

mutation first RED row
local_serve declares FLEET ..._DECLARES_the_user_machine_posture
nice_level() always 0 ..._mint_child_NICES_ITSELF
entry_ceiling() never narrows ..._entry_CEILING_halves_...
rss_reserve_bytes() never raises ..._leaves_more_HOST_RAM_alone
cpu_budget_cores() never halves ..._takes_at_most_HALF_the_cores
child does not arm PDEATHSIG ..._DIES_WITH_ITS_PARENT
frames never reach the terminal ..._never_displaces_the_HUB_activity
width row omits the posture ..._SAYS_which_posture_chose_K

Gates

mypy clean (266 files), ruff clean, all eight lint guards pass, changelog fragment checks. 36 new rows + the 15 pgw#1127 fence rows green. $0: no pods, no mints, no GPU.

Coordination

  • pgw#1111 (1111-mint-parallelism-restore, PARKED at 547b6d81, not a PR) has a WIP nice_children + preexec_fn on EntryCompilePool. This supersedes that half: the posture lives on the request, the nice happens in the child, and the AST fence refuses preexec_fn. Its owed items (a)/(b)/(c) — the meta round-trip and unclamping K — are untouched and still theirs; when they land, the entry children inherit this nice for free.
  • Does not touch aot_mint.py (pgw#1132's surface) or structure_only.py.

Still open on pgw#1127

Items 5 (memo-sweep user surface), 7 (durable store root on community cloud, tensorhub) and 8 (the two-run pod proof).

…lite — declared, not toggled

pgw#1127 S1 pointed `cozy serve` at the real mint chain, so cozy-local now
compiles on a desktop using clamps that were all written for a serving pod with
a co-resident TENANT rather than a co-resident HUMAN. §6 of that issue recorded
the evidence: zero `os.nice` calls anywhere in src/.

THE FACT IS DECLARED, NOT SNIFFED. `compile_posture.CompilePosture` carries it,
`local_serve` is the one site that says USER_MACHINE, and it rides `MintRequest`
as a typed field beside `vram_cap_bytes`. Three near-miss proxies are rejected
in the module docstring and fenced by a test: `trust_class()` and
`publisher is None` are facts about the SINK (a rented community-cloud pod
matches both and has nobody on it), and `worker_goals` says what a pod was
BOUGHT to do. Not an env either — §1.17, an env may carry a VALUE, not a
DECISION.

CPU: the mint child nices ITSELF to 19. Not a `preexec_fn` — that forces fork()
over posix_spawn() for a process with live gRPC threads and pthread_atfork
handlers, which `arm_parent_death_signal`'s docstring already writes down. It
also covers strictly more: since pgw#1080 every production mint is weight-free
and therefore SERIAL in that very process, so nicing the pool's spawns would
nice a path that does not run today. Nice is inherited, so one call covers the
serial compile, the entry children when pgw#1111 restores them, inductor's
workers and every cc1plus. `entry_workers` also halves the core budget and the
ceiling (8 -> 4): priority preserves interactivity, but does nothing for K
concurrent cc1plus, K inductor caches and K working sets in the page cache.

MEMORY: the host reserve doubles to 8 GiB. MemAvailable counts the user's page
cache as free, and a mint that OOMs a desktop is worse than a slow one.

HONESTY: the compile now says what it is, that it happens once, where the cell
goes, what it is taking, and that Ctrl-C is safe — then a throttled progress
line every 10 s. Before this the only signals were an activity addressed to a
hub cozy-local does not have and a logger.info inside a subprocess.

INTERRUPTIBILITY: the child arms PR_SET_PDEATHSIG on a user machine. It is
spawned start_new_session=True, so a closed terminal left a full-speed compile
tree running with nobody to reap it. `aot_resume`'s bank already sits outside
the per-attempt workdir, so nothing finished is lost.

THE POD IS UNTOUCHED. FLEET is the struct default everywhere, and the width is
proven arithmetically identical against an independent re-implementation of the
pre-issue formula over six pod shapes. Every politeness claim is individually
mutation-proven RED; the whole file is a collection error on origin/master.

Rejected with reasons: an interactivity probe (cross-platform mess, and wrong
for the developer running a build in a terminal — nice already IS the yield),
ionice (no stdlib wrapper, a no-op on the schedulers desktops ship), and a third
posture for community cloud.
@PaulFidika
PaulFidika merged commit c7b0813 into master Aug 11, 2026
3 of 4 checks passed
@PaulFidika
PaulFidika deleted the 1137-compile-politeness branch August 11, 2026 19:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant