diff --git a/CREDITS b/CREDITS index de2a5fa6b..22f604c43 100644 --- a/CREDITS +++ b/CREDITS @@ -298,3 +298,8 @@ N: desbma W: https://github.com/desbma C: France I: 628 + +N: John Burnett +W: http://www.johnburnett.com/ +C: Irvine, CA, US +I: 614 diff --git a/HISTORY.rst b/HISTORY.rst index 0f5eed069..683b7d091 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -37,6 +37,8 @@ Bug tracker at https://github.com/giampaolo/psutil/issues - #593: [FreeBSD] Process().memory_maps() segfaults. - #606: Process.parent() may swallow NoSuchProcess exceptions. - #611: [SunOS] net_io_counters has send and received swapped +- #614: [Linux]: cpu_count(logical=False) return the number of physical CPUs + instead of physical cores. - #618: [SunOS] swap tests fail on Solaris when run as normal user - #628: [Linux] Process.name() truncates process name in case it contains spaces or parentheses. diff --git a/psutil/__init__.py b/psutil/__init__.py index b8e6b690f..9e8cb7408 100644 --- a/psutil/__init__.py +++ b/psutil/__init__.py @@ -1342,7 +1342,7 @@ def cpu_count(logical=True): os.cpu_count() in Python 3.4). If logical is False return the number of physical cores only - (hyper thread CPUs are excluded). + (e.g. hyper thread CPUs are excluded). Return None if undetermined. diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py index a7cac31c2..668154bb3 100644 --- a/psutil/_pslinux.py +++ b/psutil/_pslinux.py @@ -276,14 +276,28 @@ def cpu_count_logical(): def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" + """Return the number of physical cores in the system.""" + mapping = {} + current_info = {} with open('/proc/cpuinfo', 'rb') as f: - found = set() for line in f: - if line.lower().startswith(b'physical id'): - found.add(line.strip()) + line = line.strip().lower() + if not line: + # new section + if (b'physical id' in current_info and + b'cpu cores' in current_info): + mapping[current_info[b'physical id']] = \ + current_info[b'cpu cores'] + current_info = {} + else: + # ongoing section + if (line.startswith(b'physical id') or + line.startswith(b'cpu cores')): + key, value = line.split(b'\t:', 1) + current_info[key] = int(value) + # mimic os.cpu_count() - return len(found) if found else None + return sum(mapping.values()) or None # --- other system functions diff --git a/test/_linux.py b/test/_linux.py index 8ac0608cd..a6cb9e417 100644 --- a/test/_linux.py +++ b/test/_linux.py @@ -204,6 +204,17 @@ def test_net_if_names(self): self.assertEqual(len(nics), found, msg="%s\n---\n%s" % ( pprint.pformat(nics), out)) + @unittest.skipUnless(which("nproc"), "nproc utility not available") + def test_cpu_count_logical_w_nproc(self): + num = int(sh("nproc --all")) + self.assertEqual(psutil.cpu_count(logical=True), num) + + @unittest.skipUnless(which("lscpu"), "lscpu utility not available") + def test_cpu_count_logical_w_lscpu(self): + out = sh("lscpu -p") + num = len([x for x in out.split('\n') if not x.startswith('#')]) + self.assertEqual(psutil.cpu_count(logical=True), num) + # --- tests for specific kernel versions @unittest.skipUnless(