Skip to content

Commit

Permalink
Speed up cpu_frequncy() on Linux systems (giampaolo#1851)
Browse files Browse the repository at this point in the history
The change is about using /proc/cpuinfo when available. It provides
cached values for frequencies and one can fill up minimum and maximum
frequency from /sys/devices/system/cpu/cpufreq/policy/* sub-system
(which is fast).

Fixes giampaolo#1851.
  • Loading branch information
marxin committed Jan 6, 2021
1 parent 51eb1da commit 59a0629
Showing 1 changed file with 21 additions and 16 deletions.
37 changes: 21 additions & 16 deletions psutil/_pslinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -719,20 +719,37 @@ def cpu_stats():
ctx_switches, interrupts, soft_interrupts, syscalls)


def _cpu_get_cpuinfo_freq():
"""Return current CPU frequency from cpuinfo if available.
"""
ret = []
with open_binary('%s/cpuinfo' % get_procfs_path()) as f:
for line in f:
if line.lower().startswith(b'cpu mhz'):
ret.append(float(line.split(b':', 1)[1]))
return ret


if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or \
os.path.exists("/sys/devices/system/cpu/cpu0/cpufreq"):
def cpu_freq():
"""Return frequency metrics for all CPUs.
Contrarily to other OSes, Linux updates these values in
real-time.
"""
cpuinfo_freqs = _cpu_get_cpuinfo_freq()
paths = sorted(
glob.glob("/sys/devices/system/cpu/cpufreq/policy[0-9]*") or
glob.glob("/sys/devices/system/cpu/cpu[0-9]*/cpufreq"))
ret = []
pjoin = os.path.join
for path in paths:
curr = cat(pjoin(path, "scaling_cur_freq"), fallback=None)
for i, path in enumerate(paths):
if len(paths) == len(cpuinfo_freqs):
# take cached value from cpuinfo if available, see:
# https://github.com/giampaolo/psutil/issues/1851
curr = cpuinfo_freqs[i]
else:
curr = cat(pjoin(path, "scaling_cur_freq"), fallback=None)
if curr is None:
# Likely an old RedHat, see:
# https://github.com/giampaolo/psutil/issues/1071
Expand All @@ -746,24 +763,12 @@ def cpu_freq():
ret.append(_common.scpufreq(curr, min_, max_))
return ret

elif os.path.exists("/proc/cpuinfo"):
else:
def cpu_freq():
"""Alternate implementation using /proc/cpuinfo.
min and max frequencies are not available and are set to None.
"""
ret = []
with open_binary('%s/cpuinfo' % get_procfs_path()) as f:
for line in f:
if line.lower().startswith(b'cpu mhz'):
key, value = line.split(b':', 1)
ret.append(_common.scpufreq(float(value), 0., 0.))
return ret

else:
def cpu_freq():
"""Dummy implementation when none of the above files are present.
"""
return []
return [_common.scpufreq(value, 0., 0.) for value in _cpu_get_cpuinfo_freq()]


# =====================================================================
Expand Down

0 comments on commit 59a0629

Please sign in to comment.