Skip to content

Efficiency follow-ups: shared scrape sample, parallel startup probes and status reconcile - #57

Merged
CMGS merged 4 commits into
mainfrom
efficiency-followups
Jul 28, 2026
Merged

Efficiency follow-ups: shared scrape sample, parallel startup probes and status reconcile#57
CMGS merged 4 commits into
mainfrom
efficiency-followups

Conversation

@CMGS

@CMGS CMGS commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Applies all four follow-ups from the whole-repo efficiency audit that closed out #56. Items 1, 2, and 4 are implemented directly here; item 3 is included through the pinned cocoon-common change from cocoonstack/cocoon-common#13.

Shared scrape sample (item 2)

The three consumers previously sampled overlapping data independently: GetStatsSummary read CPU, RSS, and network counters; GetMetricsResource read CPU and RSS; and the Prometheus collector also read network, COW, and node-storage data. They now share one complete sample behind a two-second TTL (sampleStats), so overlapping scrapes reuse the same /proc and filesystem reads. A scrape that starts a fresh sample collects the complete set, and reported values may trail the live sources by up to two seconds.

Per-VM CPU and RSS now come from one /proc/<pid>/stat read. RSS field 24 replaces the separate /proc/<pid>/status VmRSS read. parseProcStat is extracted and tested with spaces and parentheses in comm.

Parallel startup probe starts (item 1)

Every adopted pod's first probe runs synchronously with a three-second timeout, and StartupReconcile gates node registration. Adopted pods are now collected and passed through fanOut(startupFanOut, ...), reducing worst-case probe startup latency from N x 3 seconds to ceil(N/8) x 3 seconds.

Parallel status drift reconcile (item 4)

The 30-second reconcilePodStatuses pass previously performed its apiserver Get and status derivation serially. It now uses fanOut(statusReconcileFanOut, ...); workers continue to log their own failures. Startup probe and stale-create work share startupFanOut, while steady-state status reconciliation has its own concurrency constant.

Single-request hibernate evidence (item 3)

fetchHibernateManifest now uses one GetManifest call. The pinned cocoon-common implementation maps an authoritative manifest 404 to snapshot.ErrManifestNotFound; all other registry errors still fail closed.

Verification

CMGS added 4 commits July 29, 2026 00:59
…s reconcile

Follow-ups from the whole-repo efficiency audit. The three scrape
consumers (stats summary, metrics resource, Prometheus collector) each
paid their own /proc+statfs sweep per VM; they now share one 2s-TTL
sample, and CPU+RSS come from a single /proc/<pid>/stat read (RSS field
24 replaces the separate status VmRSS read — same resident-set
definition). StartupReconcile's adopted-pod probe starts move to a
bounded fan-out: each first probe is synchronous with a 3s worst case
and the loop gates node registration. reconcilePodStatuses gets the
same bounded fan-out; the three reconcile paths share reconcileFanOut.
cocoon-common's typed manifest 404 (cocoonstack/cocoon-common#13) lands
via the pseudo-version bump, so fetchHibernateManifest drops its
HasManifest HEAD: absence comes back as ErrManifestNotFound, every other
error keeps failing closed. One registry round trip per wake and per
create-time evidence check instead of two.
fanOut collapses the two policy-identical bounded fan-outs (probe
starts inline at the call site, status reconcile's closure drops its
error ceremony); the shared constant splits by lifecycle into
startupFanOut and statusReconcileFanOut so steady-state apiserver
concurrency tunes independently of the boot gate; buildNetworkStats
drops the disjunct the upstream sample already implies; narration
trimmed from the sample/parse/evidence comments. Skipped as adjudicated:
Manager.StartBatch (single-consumer API), a lazily-split sample cache
(codex round-1 rebuttal), a generic TTL-cache type (one instantiation).
@CMGS
CMGS merged commit 40d80bb into main Jul 28, 2026
4 checks passed
@CMGS
CMGS deleted the efficiency-followups branch July 28, 2026 18:02
CMGS added a commit that referenced this pull request Jul 29, 2026
…sumed hibernate (#59)

* Startup convergence: re-invoke the reclaim verb, and boot before a resumed hibernate

Fault-injection follow-up to #55/#56/#57, both reproduced on a real node.

watchBusyCreate only called Runtime.Inspect. A creating record reads the same
whether its owner is still cloning or died holding the name, so a clone whose
owner was SIGKILLed was never reclaimed: the loop polled until the 30-minute
budget expired while every CreatePod retry failed on `reserve VM record: vm
name ... already exists`. The verb is the only thing that tells those apart, so
the loop now re-invokes it each tick, short-circuiting on collected/not-found.
It stays additive: a record that reaches running is still adopted whatever the
verb answers, so a verb that keeps failing cannot strand a committed clone.
The Inspect classification is now shared with reconcileStaleCreates.

dispatchResume gated its Start on the VM state carried in the startup List
snapshot. That is a stored record field, and it does not reliably describe
liveness -- runningVMClientWithRecord's `pid %d not cloud-hypervisor` branch is
only reachable when the record still reads running, so a hibernate owed on a VM
whose VMM had been killed could skip the boot and then fail every step with
`vm is not running`. Start is idempotent (PrepareStart no-ops on a live VM and
converges a crashed one via convergeCrashedStart), so it is now unconditional.

Verified on internal-cocoon-node-7:

- kill -KILL vk with `cocoon vm clone` in flight, RestartSec shortened so vk is
  back while the orphaned child still holds the name: stale_create_reconcile
  goes busy=2 -> collected=1 and the record resolves in 6s, where the old build
  logged busy once and then went quiet for the full budget.
- stop vk mid-hibernate then SIGKILL the VMM: startup_resume_total{hibernate}=1,
  the VM boots, and the hibernate completes (netresize/snapshot/push/remove all
  ok). A marker file written into the guest before each hibernate was present
  after every wake, so no guest state was lost on either path.

* review: tighten comments, share stale-create metric recording, drop dead test knobs

* docs: describe stale-create watcher retries

* test: deliver mid-wait hibernate as a fresh tracked snapshot, not an in-place mutation

---------

Co-authored-by: CMGS <ilskdw@gmail.com>
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