package main import ( "git.novox.be/novox/mesh-sdk/go/buildcpu" "git.novox.be/novox/mesh-sdk/go/buildstep" ) // The processors a step may take (novox/hq ADR 0553, issue 1806). The node-engine holds this module's runtime, with // every other build module's of the node, in one slice at idle priority under the node's one share of its processors: // that quota bounds the total. Threads only size each step: the share the composer gives (buildstep.NodeLimits) over // this module's own capacity, so a step does not wait in the kernel's throttle. Without the composer's share there is // no slice to size a step to, and no thread limit is set. // cpuLimits is what one step is held to now. func (m *Module) cpuLimits() buildcpu.Limits { slots := 1 switch { case m.Held != nil: slots = m.Held.CapacityNow() // the capacity the puller judges by, bounded by the node's build slice case m.Capacity != nil: slots = m.Capacity() case m.Settings != "": slots = buildstep.NodeCapacity(m.Settings, buildstep.DefaultCapacities, m.Node, nil)() } return buildstep.NodeLimits(slots) } // threadEnv is the environment (nothing without a share) every command of a step is given for its threads: GOMAXPROCS for esbuild and every Go // program, UV_THREADPOOL_SIZE for Node's worker pool. func (m *Module) threadEnv() []string { return buildcpu.Env(m.cpuLimits().Threads) } // cpuStatus is what the status tool says of it: the limits a step is given, and what the kernel holds this runtime // to (its unit and its slice), read from its cgroup rather than assumed. func (m *Module) cpuStatus() map[string]any { out := map[string]any{"limits": m.cpuLimits(), "in-force": buildcpu.ReadInForce()} if m.Held != nil { out["capacity"] = m.Held.CapacityDetail() // the capacity judged by and why (issue 1806's follow-up) } return out }