feat: add getCPU() with cgroup limit support#38
Merged
Merged
Conversation
Returns CPU capacity as a float, honouring cgroup v2/v1 cfs quota and cpuset pinning so Docker/Kubernetes CPU limits are reflected (e.g. a 500m limit returns 0.5). When both quota and cpuset are set, the more restrictive value wins. Falls back to the host core count when no limit is configured. Marks getCPUCores() as deprecated. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Greptile Summary
Confidence Score: 5/5This PR is safe to merge; no new P1 or P0 issues were found and all previously flagged concerns have been resolved. Every issue from the prior review thread has a concrete fix in the diff. The cgroup parsing logic handles edge cases (max keyword, zero-period guard, unrestricted cpuset detection). No new bugs were identified. No files require special attention. Important Files Changed
Reviews (5): Last reviewed commit: "fix: guard against inverted ranges in co..." | Re-trigger Greptile |
wmic prints a header line before the numeric value, so intval() on the raw output returns 0. Extract the first numeric token instead. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previously, if /proc/cpuinfo was unreadable and no cgroup limit applied, getCPU() would silently return 0.0. Throw a descriptive exception in that case so callers don't get a value that violates the contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cgroup v2 always exposes cpuset.cpus.effective listing every CPU even when no user-visible cpuset restriction is configured. Compare the set against /sys/devices/system/cpu/online and return null when it covers all of them, so the v1 fallback remains reachable and "no restriction" is no longer misrepresented as "cpuset = all CPUs". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both branches previously fell through to 0.0 when shell_exec was disabled or returned no numeric output, breaking the >0 contract that the Linux branch and tests rely on. Throw a descriptive exception instead, matching the Linux behaviour. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
shell_exec can return string|false|null; use is_string() before passing to preg_match to satisfy static analysis. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
wmic emits one NumberOfCores row per socket, so preg_match captured only the first and undercounted multi-socket systems. Use preg_match_all and sum the values. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
An input like "3-1" previously produced a negative increment; require start <= end before counting. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
levivannoort
approved these changes
May 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
System::getCPU(): float, returning CPU capacity that honours cgroup v2 (cpu.max) and cgroup v1 (cpu.cfs_quota_us/cpu.cfs_period_us) — so Docker/Kubernetes limits like--cpus=0.5orlimits.cpu: 500mare reflected as0.5.--cpuset-cpus=0-3); when both a cfs quota and a cpuset are configured, the more restrictive value is returned.sysctl/wmicpaths on Darwin / Windows.getCPUCores()as@deprecatedin favour of the new method.Test plan
php -lclean onsrc/System/System.phpandtests/System/SystemTest.phptestGetCPUasserting float and> 0--cpus=0.5returns0.5--cpuset-cpus=0-1returns2.0