ecluse
Safe HaskellNone
LanguageGHC2021

Ecluse.Rts

Description

Resolving and applying the process's runtime posture: the capability count, the allocation area and the heap ceiling.

The RTS sizes itself from the machine, not the pod. Bare -N claims a capability per visible processor, a cgroup CPU quota does not shrink that count, and the heap is unbounded unless -M says so, leaving the kernel OOM killer as the only backstop. Neither -A nor -M has an in-process setter, so applying one re-executes this binary in place once, guarded by reexecMarker. Sizes are bytes throughout.

Synopsis

Applying the resolved posture at boot

applyRuntimePosture :: (Text -> IO ()) -> (Text -> IO ()) -> RuntimeOverrides -> IO EffectiveRuntimePlan Source #

Resolve the runtime plan and apply it, first thing at boot. It never aborts the boot, and the plan it returns is the effective one, so downstream sizing computes from what the RTS runs with.

The pure resolution core

data RtsPosture Source #

The RTS posture the process is actually running with, read at boot by currentRtsPosture.

Constructors

RtsPosture 

Fields

Instances

Instances details
Show RtsPosture Source # 
Instance details

Defined in Ecluse.Rts

Eq RtsPosture Source # 
Instance details

Defined in Ecluse.Rts

data CgroupLimits Source #

What the cgroup (v2) grants this process: the CPU quota in cores and the memory ceiling in bytes. Nothing per axis when the file is absent or carries the unlimited max sentinel.

Instances

Instances details
Show CgroupLimits Source # 
Instance details

Defined in Ecluse.Rts

Eq CgroupLimits Source # 
Instance details

Defined in Ecluse.Rts

data RuntimeOverrides Source #

The runtime configuration the resolution reads. Each unset field falls to the next rung, and roCoresCeiling bounds the last rung alone.

Instances

Instances details
Show RuntimeOverrides Source # 
Instance details

Defined in Ecluse.Rts

Eq RuntimeOverrides Source # 
Instance details

Defined in Ecluse.Rts

data Provenance Source #

Where a resolved value came from, for the boot log's provenance clause.

Constructors

FromConfig

Explicit Écluse configuration (cores / maxHeapBytes).

FromCgroup

Derived from the cgroup CPU quota, or from memory.max on the heap axis.

FromCgroupMemory

Bounded by what the cgroup memory limit can feed, for want of a CPU quota.

FromCoresCeiling

Capped at coresCeiling, with no cgroup limit of either kind in force.

FromHeapCeiling

Fitted to a heap ceiling from config, or from GHCRTS with no cgroup memory limit in force.

FromRts

Left as the RTS resolved it (baked defaults plus any operator GHCRTS).

Instances

Instances details
Show Provenance Source # 
Instance details

Defined in Ecluse.Rts

Eq Provenance Source # 
Instance details

Defined in Ecluse.Rts

data RuntimePlan Source #

The resolved runtime posture: the capability count, allocation area and heap ceiling to run with, each with its provenance. A FromRts entry means leave the live posture alone.

Instances

Instances details
Show RuntimePlan Source # 
Instance details

Defined in Ecluse.Rts

Eq RuntimePlan Source # 
Instance details

Defined in Ecluse.Rts

provenanceClause :: Provenance -> Text Source #

The provenance as a bare clause, for consumers composing their own log lines.

resolveRuntimePlan :: RuntimeOverrides -> CgroupLimits -> RtsPosture -> RuntimePlan Source #

Resolve the runtime plan: capabilities down the four-rung ladder, the heap ceiling from maxHeapBytes, else the cgroup limit, else GHCRTS, and the allocation area to fit either bound.

deriveMaxHeapBytes :: Int -> Int -> Int Source #

The heap ceiling derived from a cgroup memory limit, floored at half the limit. The nursery counts inside -M (GHC 9.6 and later), so only an overshoot allowance and off-heap memory come off.

deriveAllocAreaBytes :: Int -> Int -> Int Source #

The per-capability allocation area for a memory limit: an eighth of the limit across the capabilities, in whole MiB from 4 to 64. A smaller nursery costs collector time, not a core.

requiredRtsFlags :: RtsPosture -> RuntimePlan -> [Text] Source #

The RTS flags the plan requires beyond the live posture, in GHCRTS syntax. A FromRts entry never contributes a flag, because it is the live posture.

The effective plan (desired reconciled with observed)

data EffectiveAxis a Source #

One axis of the runtime posture after the boot applied the plan. An apply can fail, so downstream sizings read effectiveCapabilities and effectiveHeapCeiling, never the desired plan.

Constructors

EffectiveAxis 

Fields

Instances

Instances details
Show a => Show (EffectiveAxis a) Source # 
Instance details

Defined in Ecluse.Rts

Eq a => Eq (EffectiveAxis a) Source # 
Instance details

Defined in Ecluse.Rts

data EffectiveRuntimePlan Source #

The runtime plan reconciled with the posture the RTS actually runs: each planned axis as a desired/observed pair, plus the observed-only datapoints downstream sizing needs.

Constructors

EffectiveRuntimePlan 

Fields

axEnforced :: Eq a => EffectiveAxis a -> Bool Source #

Whether the live RTS backs an axis (desired and observed agree).

reconcileRuntimePlan :: CgroupLimits -> RuntimePlan -> RtsPosture -> EffectiveRuntimePlan Source #

Pair the desired plan with the posture the RTS reports, axis by axis.

appliedRuntimePlan :: CgroupLimits -> RuntimePlan -> RtsPosture -> EffectiveRuntimePlan Source #

The effective plan a successful application would produce, observed equal to desired. check-config sizes from this because it applies nothing, so its own posture is not the boot's.

effectiveCapabilities :: EffectiveRuntimePlan -> (Int, Provenance) Source #

The live capability count: budgets must never exceed what the RTS actually runs with, so the observed side is authoritative. An unenforced count degrades the provenance to FromRts.

effectiveHeapCeiling :: EffectiveRuntimePlan -> (Maybe Int, Provenance) Source #

The sizing ceiling: the tighter of desired and observed. An observed -M below the plan binds, and an absent one leaves the desired ceiling standing on the cgroup limit's OOM backstop.

renderEffectivePosture :: EffectiveRuntimePlan -> [Text] Source #

The boot log's posture lines, one decision per line with its provenance. The allocation area has no config key: the cgroup limit or an operator GHCRTS sets it.

renderPostureWarnings :: EffectiveRuntimePlan -> [Text] Source #

The boot log's posture warnings: an axis the RTS is not enforcing, and a capability count no entitlement backs.

Cgroup v2 parsing

parseCpuMax :: Text -> Maybe Double Source #

Parse a cgroup-v2 cpu.max body. "quota period" yields the granted cores, and the max sentinel or a malformed body yields Nothing: no limit is inferred from noise.

parseMemoryMax :: Text -> Maybe Int Source #

Parse a cgroup-v2 memory.max body: a byte count, or the unlimited max sentinel (Nothing). A malformed body yields Nothing.

readIfExists :: FilePath -> IO (Maybe Text) Source #

Read a file that may be absent, as off a cgroup-v2 host. Every other IO error propagates.

parseInactiveFile :: Text -> Maybe Int Source #

The inactive_file bytes in a cgroup-v2 memory.stat body: page cache the kernel reclaims first.

usePermille :: Int -> Maybe Int -> Int -> Int Source #

Memory in use less reclaimable page cache, in thousandths of the limit, from a cgroup's readings.

Cgroup memory use

cgroupMemoryUse :: IO (IO (Maybe Int)) Source #

A reader for this process's cgroup memory use less reclaimable file pages, in thousandths of the tightest memory.max above it. It reads Nothing when no limit binds or a read fails.