perf: Process.cpu_percent() no longer calls cpu_count() - #2955
Open
Dipet wants to merge 1 commit into
Open
Conversation
Dipet
force-pushed
the
perf/cpu-percent-drop-redundant-cpu-count
branch
from
August 7, 2026 15:52
5039066 to
bcd619e
Compare
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
Description
Process.cpu_percent()callscpu_count()on every invocation, but the value cancels out algebraically:num_cpusappears once in the denominator and once in the numerator, so the returned value never depends on it. Verified empirically by forcingcpu_count()to return 1, 8, 128 and 1000 while sampling a busy-loop process: the result is100.0in all four cases.On Linux
cpu_count_logical()is asysconf(SC_NPROCESSORS_ONLN)call, so iterating over all processes pays it once per process. On a host with ~15 300 processes:process_iter()with 12 attrsposix.sysconfdisappears from the profile entirely — 15 242 calls → 0.This also removes a latent correctness issue. In the non-blocking form
st1comes from a previous call. If the logical CPU count changed in between (CPU hotplug),st1andst2were scaled by different factors and the returned percentage was wrong. Without the factor the two samples are always comparable.test_cpu_percent_numcpus_noneasserted thatcpu_counthad been called, an implementation detail that no longer exists. It now asserts the guarantee issue #1087 actually asked for:cpu_percent()works whencpu_count()returnsNone. Theor 1guard is no longer needed since nothing divides by it any more.Tests:
tests/test_process.py tests/test_system.py tests/test_misc.py tests/test_contracts.py→ 249 passed.test_long_nameandtest_memory_maps_lists_libfail identically on unmodified master in this environment, so they are unrelated to this change.