Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speed up cpu_frequncy() on Linux systems (#1851). #1852

Merged
merged 1 commit into from
Jan 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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(x, 0., 0.) for x in _cpu_get_cpuinfo_freq()]


# =====================================================================
Expand Down
4 changes: 0 additions & 4 deletions psutil/tests/test_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -768,18 +768,14 @@ def path_exists_mock(path):
if path.startswith('/sys/devices/system/cpu/'):
return False
else:
if path == "/proc/cpuinfo":
flags.append(None)
return os_path_exists(path)

flags = []
os_path_exists = os.path.exists
try:
with mock.patch("os.path.exists", side_effect=path_exists_mock):
reload_module(psutil._pslinux)
ret = psutil.cpu_freq()
assert ret
assert flags
self.assertEqual(ret.max, 0.0)
self.assertEqual(ret.min, 0.0)
for freq in psutil.cpu_freq(percpu=True):
Expand Down