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

Fix cpu freq #1496

Merged
merged 10 commits into from
Apr 26, 2019
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
24 changes: 18 additions & 6 deletions psutil/_pslinux.py
Original file line number Diff line number Diff line change
Expand Up @@ -668,7 +668,7 @@ def cpu_stats():
ctx_switches, interrupts, soft_interrupts, syscalls)


if os.path.exists("/sys/devices/system/cpu/cpufreq") or \
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.
Expand Down Expand Up @@ -708,13 +708,25 @@ def cpu_freq():
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'\t:', 1)
ret.append(_common.scpufreq(float(value), 0.0, 0.0))
path = '%s/cpuinfo' % get_procfs_path()
if os.path.exists(path):
try:
with open_binary(path) as f:
for line in f:
if line.lower().startswith(b'cpu mhz'):
key, value = line.split(b'\t:', 1)
ret.append(_common.scpufreq(float(value), 0., 0.))
except IOError as err:
raise NotImplementedError(
"%r for file %r" % (err, path))
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm... Not sure I understand why catching IOError is necessary here. Isn't the function declaration guarded by if os.path.exists("/proc/cpuinfo"): already?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return ret

else:
def cpu_freq():
"""Dummy implementation when none of the above files are present.
"""
return []


# =====================================================================
# --- network
Expand Down
29 changes: 23 additions & 6 deletions psutil/tests/test_linux.py
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,8 @@ def open_mock(name, *args, **kwargs):
elif (name.endswith('/scaling_max_freq') and
name.startswith("/sys/devices/system/cpu/cpufreq/policy")):
return io.BytesIO(b"700000")
elif name == '/proc/cpuinfo':
return io.BytesIO(b"cpu MHz : 500")
else:
return orig_open(name, *args, **kwargs)

Expand All @@ -770,8 +772,12 @@ def open_mock(name, *args, **kwargs):
'os.path.exists', return_value=True):
freq = psutil.cpu_freq()
self.assertEqual(freq.current, 500.0)
self.assertEqual(freq.min, 600.0)
self.assertEqual(freq.max, 700.0)
# when /proc/cpuinfo is used min and max frequencies are not
# available and are set to 0.
if freq.min != 0.0:
self.assertEqual(freq.min, 600.0)
if freq.max != 0.0:
self.assertEqual(freq.max, 700.0)

@unittest.skipIf(not HAS_CPU_FREQ, "not supported")
def test_emulate_multi_cpu(self):
Expand All @@ -795,6 +801,9 @@ def open_mock(name, *args, **kwargs):
elif (n.endswith('/scaling_max_freq') and
n.startswith("/sys/devices/system/cpu/cpufreq/policy1")):
return io.BytesIO(b"600000")
elif name == '/proc/cpuinfo':
return io.BytesIO(b"cpu MHz : 100\n"
b"cpu MHz : 400")
else:
return orig_open(name, *args, **kwargs)

Expand All @@ -806,11 +815,15 @@ def open_mock(name, *args, **kwargs):
return_value=2):
freq = psutil.cpu_freq(percpu=True)
self.assertEqual(freq[0].current, 100.0)
self.assertEqual(freq[0].min, 200.0)
self.assertEqual(freq[0].max, 300.0)
if freq[0].min != 0.0:
self.assertEqual(freq[0].min, 200.0)
if freq[0].max != 0.0:
self.assertEqual(freq[0].max, 300.0)
self.assertEqual(freq[1].current, 400.0)
self.assertEqual(freq[1].min, 500.0)
self.assertEqual(freq[1].max, 600.0)
if freq[1].min != 0.0:
self.assertEqual(freq[1].min, 500.0)
if freq[1].max != 0.0:
self.assertEqual(freq[1].max, 600.0)

@unittest.skipIf(TRAVIS, "fails on Travis")
@unittest.skipIf(not HAS_CPU_FREQ, "not supported")
Expand All @@ -821,6 +834,8 @@ def open_mock(name, *args, **kwargs):
raise IOError(errno.ENOENT, "")
elif name.endswith('/cpuinfo_cur_freq'):
return io.BytesIO(b"200000")
elif name == '/proc/cpuinfo':
return io.BytesIO(b"cpu MHz : 200")
else:
return orig_open(name, *args, **kwargs)

Expand All @@ -841,6 +856,8 @@ def open_mock(name, *args, **kwargs):
raise IOError(errno.ENOENT, "")
elif name.endswith('/cpuinfo_cur_freq'):
raise IOError(errno.ENOENT, "")
elif name == '/proc/cpuinfo':
raise IOError(errno.ENOENT, "")
else:
return orig_open(name, *args, **kwargs)

Expand Down
3 changes: 2 additions & 1 deletion psutil/tests/test_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,8 @@ def test_cpu_freq(self):
def check_ls(ls):
for nt in ls:
self.assertEqual(nt._fields, ('current', 'min', 'max'))
self.assertLessEqual(nt.current, nt.max)
if nt.max != 0.0:
self.assertLessEqual(nt.current, nt.max)
for name in nt._fields:
value = getattr(nt, name)
self.assertIsInstance(value, (int, long, float))
Expand Down