Skip to main content

Resource Limits

Runix can enforce CPU and memory limits on processes using Linux cgroups v2.

Implementation​

Located at internal/cgroups/:

FileResponsibility
manager.goManager interface and helper functions
manager_linux.goLinux cgroups v2 implementation
manager_other.goNo-op implementation for non-Linux platforms

Configuration​

processes:
api:
entrypoint: ./cmd/api
resources:
cpu_quota: "50%"
memory_limit: "512MB"

heavy-worker:
entrypoint: worker.py
resources:
cpu_quota: "200%"
memory_limit: "2GB"

Fields​

FieldTypeDescription
cpu_quotastringCPU limit as percentage (e.g., "50%", "200%")
memory_limitstringMemory limit with unit (e.g., "512MB", "1GB", "1024KB")

Memory Units​

UnitMultiplier
KB1024
MB1,048,576
GB1,073,741,824

Platform Support​

PlatformSupport
Linux (cgroups v2)Full — CPU and memory limits enforced
macOSNot supported — returns error if limits are configured
WindowsNot supported — returns error if limits are configured

How It Works (Linux)​

cgroup Structure​

/sys/fs/cgroup/runix/<pid>/
├── cgroup.procs # Process membership
├── cpu.max # CPU quota and period
└── memory.max # Memory limit in bytes

CPU Quota​

CPU quota is converted from percentage to microseconds per 100ms period:

Configcpu.max
"50%"50000 100000
"100%"100000 100000
"200%"200000 100000

Memory Limit​

Memory limit is converted to bytes and written to memory.max:

ConfigBytes
"512MB"536870912
"1GB"1073741824

Lifecycle​

  1. On start: Create cgroup at /sys/fs/cgroup/runix/<pid>/, add PID, set limits
  2. On stop: Remove the cgroup directory
  3. Stats: Read memory.current for current memory usage

No-op Implementation​

On non-Linux platforms, the noopManager returns an error if limits are configured:

func (m *noopManager) Apply(pid int, limits Limits) error {
if limits.CPUQuota != "" || limits.MemoryLimit != "" {
return fmt.Errorf("resource limits require cgroups v2 (Linux only)")
}
return nil
}

What's Next​