summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormarxin <marxin.liska@gmail.com>2021-01-07 12:04:51 +0100
committerGitHub <noreply@github.com>2021-01-07 12:04:51 +0100
commit6e494bd4024c3d25769688b53e95942e529392d6 (patch)
tree841f5d9b8e1dd463ded08091bda0c8c8f819c486
parentf95276d744dee12a237d1a3f2836f36340c6abc0 (diff)
downloadpsutil-6e494bd4024c3d25769688b53e95942e529392d6.tar.gz
Speed up cpu_frequncy() on Linux systems (#1851) (#1852)
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 #1851.
-rw-r--r--psutil/_pslinux.py37
-rwxr-xr-xpsutil/tests/test_linux.py4
2 files changed, 21 insertions, 20 deletions
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
index ff8d9247..640a0f3d 100644
--- a/psutil/_pslinux.py
+++ b/psutil/_pslinux.py
@@ -719,6 +719,17 @@ 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():
@@ -726,13 +737,19 @@ if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or \
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
@@ -746,24 +763,12 @@ if os.path.exists("/sys/devices/system/cpu/cpufreq/policy0") or \
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()]
# =====================================================================
diff --git a/psutil/tests/test_linux.py b/psutil/tests/test_linux.py
index 2f6065f5..0c6d498c 100755
--- a/psutil/tests/test_linux.py
+++ b/psutil/tests/test_linux.py
@@ -768,18 +768,14 @@ class TestSystemCPUFrequency(PsutilTestCase):
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):