diff options
-rw-r--r-- | HISTORY.rst | 11 | ||||
-rw-r--r-- | MANIFEST.in | 1 | ||||
-rw-r--r-- | appveyor.yml | 18 | ||||
-rw-r--r-- | docs/index.rst | 17 | ||||
-rw-r--r-- | psutil/_psutil_common.c | 2 | ||||
-rw-r--r-- | psutil/_psutil_windows.c | 197 | ||||
-rw-r--r-- | psutil/_pswindows.py | 2 | ||||
-rw-r--r-- | psutil/arch/windows/glpi.h | 41 | ||||
-rwxr-xr-x | psutil/tests/test_system.py | 7 | ||||
-rwxr-xr-x | psutil/tests/test_windows.py | 48 |
10 files changed, 195 insertions, 149 deletions
diff --git a/HISTORY.rst b/HISTORY.rst index 65cad58e..b5fad59c 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -15,6 +15,12 @@ XXXX-XX-XX - 694_: [SunOS] cmdline() could be truncated at the 15th character when reading it from /proc. An extra effort is made by reading it from process address space first. (patch by Georg Sauthoff) +- 771_: [Windows] cpu_count() (both logical and physical) return a wrong + (smaller) number on systems using process groups (> 64 cores). +- 771_: [Windows] cpu_times(percpu=True) return fewer CPUs on systems using + process groups (> 64 cores). +- 771_: [Windows] cpu_stats() and cpu_freq() may return incorrect results on + systems using process groups (> 64 cores). - 1193_: [SunOS] Return uid/gid from /proc/pid/psinfo if there aren't enough permissions for /proc/pid/cred. (patch by Georg Sauthoff) - 1194_: [SunOS] Return nice value from psinfo as getpriority() doesn't @@ -38,6 +44,11 @@ XXXX-XX-XX - 1255_: [FreeBSD] swap_memory() stats were erroneously represented in KB. (patch by Denis Krienbühl) +**Backward compatibility** + +- 771_: [Windows] cpu_count(logical=False) on Windows XP and Vista is no + longer supported and returns None. + 5.4.3 ===== diff --git a/MANIFEST.in b/MANIFEST.in index 87d9bebb..85d1f21e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -67,7 +67,6 @@ include psutil/arch/solaris/environ.c include psutil/arch/solaris/environ.h include psutil/arch/solaris/v10/ifaddrs.c include psutil/arch/solaris/v10/ifaddrs.h -include psutil/arch/windows/glpi.h include psutil/arch/windows/inet_ntop.c include psutil/arch/windows/inet_ntop.h include psutil/arch/windows/ntextapi.h diff --git a/appveyor.yml b/appveyor.yml index f39053ad..436faadb 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -45,20 +45,13 @@ environment: - PYTHON: "C:\\Python35-x64" PYTHON_VERSION: "3.5.x" PYTHON_ARCH: "64" - ARCH: x86_64 - VS_VER: "2015" - INSTANCENAME: "SQL2012SP1" - PYTHON: "C:\\Python36-x64" PYTHON_VERSION: "3.6.x" PYTHON_ARCH: "64" - ARCH: x86_64 - VS_VER: "2015" - INSTANCENAME: "SQL2012SP1" # Also build on a Python version not pre-installed by Appveyor. # See: https://github.com/ogrisel/python-appveyor-demo/issues/10 - # - PYTHON: "C:\\Python266" # PYTHON_VERSION: "2.6.6" # PYTHON_ARCH: "32" @@ -71,20 +64,17 @@ install: # - ps: (new-object net.webclient).DownloadFile('https://raw.github.com/pypa/pip/master/contrib/get-pip.py', 'C:/get-pip.py') - "%WITH_COMPILER% %PYTHON%/python.exe -m pip --version" - "%WITH_COMPILER% %PYTHON%/python.exe -m pip install --upgrade --user setuptools pip" - - "%WITH_COMPILER% %PYTHON%/python.exe -m pip freeze" - - "%WITH_COMPILER% %PYTHON%/python.exe setup.py build" - - "%WITH_COMPILER% %PYTHON%/python.exe setup.py build build_ext -i" - - "%WITH_COMPILER% %PYTHON%/python.exe setup.py develop" - "%WITH_COMPILER% %PYTHON%/python.exe scripts/internal/winmake.py setup-dev-env" + - "%WITH_COMPILER% %PYTHON%/python.exe -m pip freeze" + - "%WITH_COMPILER% %PYTHON%/python.exe scripts/internal/winmake.py install" build: off test_script: - - "%WITH_COMPILER% %PYTHON%/python -V" - - "set PYTHONWARNINGS=all && set PSUTIL_TESTING=1 && set PSUTIL_DEBUG=1 && %WITH_COMPILER% %PYTHON%/python psutil/tests/__main__.py" + - "%WITH_COMPILER% %PYTHON%/python.exe scripts/internal/winmake.py test" after_test: - - "%WITH_COMPILER% %PYTHON%/python setup.py bdist_wheel" + - "%WITH_COMPILER% %PYTHON%/python.exe scripts/internal/winmake.py wheel" artifacts: - path: dist\* diff --git a/docs/index.rst b/docs/index.rst index 395fd688..548f361f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -164,15 +164,11 @@ CPU Return the number of logical CPUs in the system (same as `os.cpu_count() <http://docs.python.org/3/library/os.html#os.cpu_count>`__ in Python 3.4) or ``None`` if undetermined. - This number may not be equivalent to the number of CPUs the current process - can actually use in case process CPU affinity has been changed or Linux - cgroups are being used. - The number of usable CPUs can be obtained with - ``len(psutil.Process().cpu_affinity())``. If *logical* is ``False`` return the number of physical cores only (hyper - thread CPUs are excluded). + thread CPUs are excluded) or ``None`` if undetermined. On OpenBSD and NetBSD ``psutil.cpu_count(logical=False)`` always return - ``None``. Example on a system having 2 physical hyper-thread CPU cores: + ``None``. + Example on a system having 2 physical hyper-thread CPU cores: >>> import psutil >>> psutil.cpu_count() @@ -180,7 +176,12 @@ CPU >>> psutil.cpu_count(logical=False) 2 - Example returning the number of CPUs usable by the current process: + Note that this number is not equivalent to the number of CPUs the current + process can actually use. + That can vary in case process CPU affinity has been changed, Linux cgroups + are being used or on Windows systems using processor groups or having more + than 64 CPUs. + The number of usable CPUs can be obtained with: >>> len(psutil.Process().cpu_affinity()) 1 diff --git a/psutil/_psutil_common.c b/psutil/_psutil_common.c index e08f011c..49b91c82 100644 --- a/psutil/_psutil_common.c +++ b/psutil/_psutil_common.c @@ -85,7 +85,7 @@ void psutil_debug(const char* format, ...) { va_list argptr; va_start(argptr, format); - fprintf(stderr, "psutil-dubug> "); + fprintf(stderr, "psutil-debug> "); vfprintf(stderr, format, argptr); fprintf(stderr, "\n"); va_end(argptr); diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c index d39afb21..ae2e538a 100644 --- a/psutil/_psutil_windows.c +++ b/psutil/_psutil_windows.c @@ -38,10 +38,6 @@ #include "arch/windows/inet_ntop.h" #include "arch/windows/services.h" -#ifdef __MINGW32__ -#include "arch/windows/glpi.h" -#endif - /* * ============================================================================ @@ -63,8 +59,13 @@ Py_DECREF(_SOCK_STREAM);\ Py_DECREF(_SOCK_DGRAM); -typedef BOOL (WINAPI *LPFN_GLPI) - (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD); +#if (_WIN32_WINNT >= 0x0601) // Windows 7 +typedef BOOL (WINAPI *PFN_GETLOGICALPROCESSORINFORMATIONEX)( + LOGICAL_PROCESSOR_RELATIONSHIP relationship, + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX Buffer, + PDWORD ReturnLength); +static PFN_GETLOGICALPROCESSORINFORMATIONEX _GetLogicalProcessorInformationEx; +#endif // Fix for mingw32, see: // https://github.com/giampaolo/psutil/issues/351#c2 @@ -196,6 +197,45 @@ psutil_get_nic_addresses() { /* + * Return the number of logical, active CPUs. Return 0 if undetermined. + * See discussion at: https://bugs.python.org/issue33166#msg314631 + */ +unsigned int +psutil_get_num_cpus(int fail_on_err) { + unsigned int ncpus = 0; + SYSTEM_INFO sysinfo; + static DWORD(CALLBACK *_GetActiveProcessorCount)(WORD) = NULL; + HINSTANCE hKernel32; + + // GetActiveProcessorCount is available only on 64 bit versions + // of Windows from Windows 7 onward. + // Windows Vista 64 bit and Windows XP doesn't have it. + hKernel32 = GetModuleHandleW(L"KERNEL32"); + _GetActiveProcessorCount = (void*)GetProcAddress( + hKernel32, "GetActiveProcessorCount"); + + if (_GetActiveProcessorCount != NULL) { + ncpus = _GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); + if ((ncpus == 0) && (fail_on_err == 1)) { + PyErr_SetFromWindowsErr(0); + } + } + else { + psutil_debug("GetActiveProcessorCount() not available; " + "using GetNativeSystemInfo()"); + GetNativeSystemInfo(&sysinfo); + ncpus = (unsigned int)sysinfo.dwNumberOfProcessors; + if ((ncpus == 0) && (fail_on_err == 1)) { + PyErr_SetString( + PyExc_RuntimeError, + "GetNativeSystemInfo() failed to retrieve CPU count"); + } + } + return ncpus; +} + + +/* * ============================================================================ * Public Python API * ============================================================================ @@ -553,55 +593,77 @@ psutil_proc_create_time(PyObject *self, PyObject *args) { } - /* - * Return the number of logical CPUs. + * Return the number of active, logical CPUs. */ static PyObject * psutil_cpu_count_logical(PyObject *self, PyObject *args) { - SYSTEM_INFO system_info; - system_info.dwNumberOfProcessors = 0; + unsigned int ncpus; - GetSystemInfo(&system_info); - if (system_info.dwNumberOfProcessors == 0) - Py_RETURN_NONE; // mimic os.cpu_count() + ncpus = psutil_get_num_cpus(0); + if (ncpus != 0) + return Py_BuildValue("I", ncpus); else - return Py_BuildValue("I", system_info.dwNumberOfProcessors); + Py_RETURN_NONE; // mimick os.cpu_count() } /* - * Return the number of physical CPU cores. + * Return the number of physical CPU cores (hyper-thread CPUs count + * is excluded). */ +#if (_WIN32_WINNT < 0x0601) // < Windows 7 (namely Vista and XP) +static PyObject * +psutil_cpu_count_phys(PyObject *self, PyObject *args) { + // Note: we may have used GetLogicalProcessorInformation() + // but I don't want to prolong support for Windows XP and Vista. + // On such old systems psutil will compile but this API will + // just return None. + psutil_debug("Win < 7; cpu_count_phys() forced to None"); + Py_RETURN_NONE; +} +#else // Windows >= 7 static PyObject * psutil_cpu_count_phys(PyObject *self, PyObject *args) { - LPFN_GLPI glpi; DWORD rc; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL; + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX buffer = NULL; + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX ptr = NULL; DWORD length = 0; DWORD offset = 0; - int ncpus = 0; - - glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")), - "GetLogicalProcessorInformation"); - if (glpi == NULL) + DWORD ncpus = 0; + + // GetLogicalProcessorInformationEx() is available from Windows 7 + // onward. Differently from GetLogicalProcessorInformation() + // it supports process groups, meaning this is able to report more + // than 64 CPUs. See: + // https://bugs.python.org/issue33166 + _GetLogicalProcessorInformationEx = \ + (PFN_GETLOGICALPROCESSORINFORMATIONEX)GetProcAddress( + GetModuleHandle(TEXT("kernel32")), + "GetLogicalProcessorInformationEx"); + if (_GetLogicalProcessorInformationEx == NULL) { + psutil_debug("failed loading GetLogicalProcessorInformationEx()"); goto return_none; + } while (1) { - rc = glpi(buffer, &length); + rc = _GetLogicalProcessorInformationEx( + RelationAll, buffer, &length); if (rc == FALSE) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - if (buffer) + if (buffer) { free(buffer); - buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc( - length); + } + buffer = \ + (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX)malloc(length); if (NULL == buffer) { PyErr_NoMemory(); return NULL; } } else { + psutil_debug("GetLogicalProcessorInformationEx() returned ", + GetLastError()); goto return_none; } } @@ -611,25 +673,30 @@ psutil_cpu_count_phys(PyObject *self, PyObject *args) { } ptr = buffer; - while (offset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= length) { - if (ptr->Relationship == RelationProcessorCore) + while (ptr->Size > 0 && offset + ptr->Size <= length) { + if (ptr->Relationship == RelationProcessorCore) { ncpus += 1; - offset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); - ptr++; + } + offset += ptr->Size; + ptr = (SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX*)\ + (((char*)ptr) + ptr->Size); } free(buffer); - if (ncpus == 0) - goto return_none; - else - return Py_BuildValue("i", ncpus); + if (ncpus != 0) { + return Py_BuildValue("I", ncpus); + } + else { + psutil_debug("GetLogicalProcessorInformationEx() count was 0"); + Py_RETURN_NONE; // mimick os.cpu_count() + } return_none: - // mimic os.cpu_count() if (buffer != NULL) free(buffer); Py_RETURN_NONE; } +#endif /* @@ -957,8 +1024,8 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) { double idle, kernel, systemt, user, interrupt, dpc; NTSTATUS status; _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL; - SYSTEM_INFO si; UINT i; + unsigned int ncpus; PyObject *py_tuple = NULL; PyObject *py_retlist = PyList_New(0); @@ -978,14 +1045,15 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) { goto error; } - // retrives number of processors - GetSystemInfo(&si); + // retrieves number of processors + ncpus = psutil_get_num_cpus(1); + if (ncpus == 0) + goto error; // allocates an array of _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION // structures, one per processor sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \ - malloc(si.dwNumberOfProcessors * \ - sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); + malloc(ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); if (sppi == NULL) { PyErr_NoMemory(); goto error; @@ -995,8 +1063,7 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) { status = NtQuerySystemInformation( SystemProcessorPerformanceInformation, sppi, - si.dwNumberOfProcessors * sizeof - (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), + ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), NULL); if (status != 0) { PyErr_SetFromWindowsErr(0); @@ -1006,7 +1073,7 @@ psutil_per_cpu_times(PyObject *self, PyObject *args) { // computes system global times summing each // processor value idle = user = kernel = interrupt = dpc = 0; - for (i = 0; i < si.dwNumberOfProcessors; i++) { + for (i = 0; i < ncpus; i++) { py_tuple = NULL; user = (double)((HI_T * sppi[i].UserTime.HighPart) + (LO_T * sppi[i].UserTime.LowPart)); @@ -3403,7 +3470,7 @@ psutil_cpu_stats(PyObject *self, PyObject *args) { _SYSTEM_PERFORMANCE_INFORMATION *spi = NULL; _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL; _SYSTEM_INTERRUPT_INFORMATION *InterruptInformation = NULL; - SYSTEM_INFO si; + unsigned int ncpus; UINT i; ULONG64 dpcs = 0; ULONG interrupts = 0; @@ -3421,13 +3488,14 @@ psutil_cpu_stats(PyObject *self, PyObject *args) { goto error; } - // retrives number of processors - GetSystemInfo(&si); + // retrieves number of processors + ncpus = psutil_get_num_cpus(1); + if (ncpus == 0) + goto error; // get syscalls / ctx switches spi = (_SYSTEM_PERFORMANCE_INFORMATION *) \ - malloc(si.dwNumberOfProcessors * \ - sizeof(_SYSTEM_PERFORMANCE_INFORMATION)); + malloc(ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION)); if (spi == NULL) { PyErr_NoMemory(); goto error; @@ -3435,7 +3503,7 @@ psutil_cpu_stats(PyObject *self, PyObject *args) { status = NtQuerySystemInformation( SystemPerformanceInformation, spi, - si.dwNumberOfProcessors * sizeof(_SYSTEM_PERFORMANCE_INFORMATION), + ncpus * sizeof(_SYSTEM_PERFORMANCE_INFORMATION), NULL); if (status != 0) { PyErr_SetFromWindowsErr(0); @@ -3444,8 +3512,7 @@ psutil_cpu_stats(PyObject *self, PyObject *args) { // get DPCs InterruptInformation = \ - malloc(sizeof(_SYSTEM_INTERRUPT_INFORMATION) * - si.dwNumberOfProcessors); + malloc(sizeof(_SYSTEM_INTERRUPT_INFORMATION) * ncpus); if (InterruptInformation == NULL) { PyErr_NoMemory(); goto error; @@ -3454,20 +3521,19 @@ psutil_cpu_stats(PyObject *self, PyObject *args) { status = NtQuerySystemInformation( SystemInterruptInformation, InterruptInformation, - si.dwNumberOfProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION), + ncpus * sizeof(SYSTEM_INTERRUPT_INFORMATION), NULL); if (status != 0) { PyErr_SetFromWindowsErr(0); goto error; } - for (i = 0; i < si.dwNumberOfProcessors; i++) { + for (i = 0; i < ncpus; i++) { dpcs += InterruptInformation[i].DpcCount; } // get interrupts sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \ - malloc(si.dwNumberOfProcessors * \ - sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); + malloc(ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); if (sppi == NULL) { PyErr_NoMemory(); goto error; @@ -3476,15 +3542,14 @@ psutil_cpu_stats(PyObject *self, PyObject *args) { status = NtQuerySystemInformation( SystemProcessorPerformanceInformation, sppi, - si.dwNumberOfProcessors * sizeof - (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), + ncpus * sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), NULL); if (status != 0) { PyErr_SetFromWindowsErr(0); goto error; } - for (i = 0; i < si.dwNumberOfProcessors; i++) { + for (i = 0; i < ncpus; i++) { interrupts += sppi[i].InterruptCount; } @@ -3525,19 +3590,15 @@ psutil_cpu_freq(PyObject *self, PyObject *args) { LPBYTE pBuffer = NULL; ULONG current; ULONG max; - unsigned int num_cpus; - SYSTEM_INFO system_info; - system_info.dwNumberOfProcessors = 0; + unsigned int ncpus; // Get the number of CPUs. - GetSystemInfo(&system_info); - if (system_info.dwNumberOfProcessors == 0) - num_cpus = 1; - else - num_cpus = system_info.dwNumberOfProcessors; + ncpus = psutil_get_num_cpus(1); + if (ncpus == 0) + return NULL; // Allocate size. - size = num_cpus * sizeof(PROCESSOR_POWER_INFORMATION); + size = ncpus * sizeof(PROCESSOR_POWER_INFORMATION); pBuffer = (BYTE*)LocalAlloc(LPTR, size); if (! pBuffer) return PyErr_SetFromWindowsErr(0); diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py index ab727cba..18651d6c 100644 --- a/psutil/_pswindows.py +++ b/psutil/_pswindows.py @@ -288,7 +288,7 @@ def cpu_count_logical(): def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" + """Return the number of physical CPU cores in the system.""" return cext.cpu_count_phys() diff --git a/psutil/arch/windows/glpi.h b/psutil/arch/windows/glpi.h deleted file mode 100644 index 6f984837..00000000 --- a/psutil/arch/windows/glpi.h +++ /dev/null @@ -1,41 +0,0 @@ -// mingw headers are missing this - -typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP { - RelationProcessorCore, - RelationNumaNode, - RelationCache, - RelationProcessorPackage, - RelationGroup, - RelationAll=0xffff -} LOGICAL_PROCESSOR_RELATIONSHIP; - -typedef enum _PROCESSOR_CACHE_TYPE { - CacheUnified,CacheInstruction,CacheData,CacheTrace -} PROCESSOR_CACHE_TYPE; - -typedef struct _CACHE_DESCRIPTOR { - BYTE Level; - BYTE Associativity; - WORD LineSize; - DWORD Size; - PROCESSOR_CACHE_TYPE Type; -} CACHE_DESCRIPTOR,*PCACHE_DESCRIPTOR; - -typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION { - ULONG_PTR ProcessorMask; - LOGICAL_PROCESSOR_RELATIONSHIP Relationship; - union { - struct { - BYTE Flags; - } ProcessorCore; - struct { - DWORD NodeNumber; - } NumaNode; - CACHE_DESCRIPTOR Cache; - ULONGLONG Reserved[2]; - }; -} SYSTEM_LOGICAL_PROCESSOR_INFORMATION,*PSYSTEM_LOGICAL_PROCESSOR_INFORMATION; - -WINBASEAPI WINBOOL WINAPI -GetLogicalProcessorInformation(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, - PDWORD ReturnedLength);
\ No newline at end of file diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py index 20b132a9..6081ea5a 100755 --- a/psutil/tests/test_system.py +++ b/psutil/tests/test_system.py @@ -268,8 +268,11 @@ class TestSystemAPIs(unittest.TestCase): if "physical id" not in cpuinfo_data: raise unittest.SkipTest("cpuinfo doesn't include physical id") physical = psutil.cpu_count(logical=False) - self.assertGreaterEqual(physical, 1) - self.assertGreaterEqual(logical, physical) + if WINDOWS and sys.getwindowsversion()[:2] <= (6, 1): # <= Vista + self.assertIsNone(physical) + else: + self.assertGreaterEqual(physical, 1) + self.assertGreaterEqual(logical, physical) def test_cpu_count_none(self): # https://github.com/giampaolo/psutil/issues/1085 diff --git a/psutil/tests/test_windows.py b/psutil/tests/test_windows.py index 32c46f67..ffa763d0 100755 --- a/psutil/tests/test_windows.py +++ b/psutil/tests/test_windows.py @@ -69,35 +69,57 @@ def wrap_exceptions(fun): @unittest.skipIf(not WINDOWS, "WINDOWS only") -class TestSystemAPIs(unittest.TestCase): - - def test_nic_names(self): - out = sh('ipconfig /all') - nics = psutil.net_io_counters(pernic=True).keys() - for nic in nics: - if "pseudo-interface" in nic.replace(' ', '-').lower(): - continue - if nic not in out: - self.fail( - "%r nic wasn't found in 'ipconfig /all' output" % nic) +class TestCpuAPIs(unittest.TestCase): @unittest.skipIf('NUMBER_OF_PROCESSORS' not in os.environ, 'NUMBER_OF_PROCESSORS env var is not available') - def test_cpu_count(self): + def test_cpu_count_vs_NUMBER_OF_PROCESSORS(self): + # Will likely fail on many-cores systems: + # https://stackoverflow.com/questions/31209256 num_cpus = int(os.environ['NUMBER_OF_PROCESSORS']) self.assertEqual(num_cpus, psutil.cpu_count()) - def test_cpu_count_2(self): + def test_cpu_count_vs_GetSystemInfo(self): + # Will likely fail on many-cores systems: + # https://stackoverflow.com/questions/31209256 sys_value = win32api.GetSystemInfo()[5] psutil_value = psutil.cpu_count() self.assertEqual(sys_value, psutil_value) + def test_cpu_count_logical_vs_wmi(self): + w = wmi.WMI() + proc = w.Win32_Processor()[0] + self.assertEqual(psutil.cpu_count(), proc.NumberOfLogicalProcessors) + + def test_cpu_count_phys_vs_wmi(self): + w = wmi.WMI() + proc = w.Win32_Processor()[0] + self.assertEqual(psutil.cpu_count(logical=False), proc.NumberOfCores) + + def test_cpu_count_vs_cpu_times(self): + self.assertEqual(psutil.cpu_count(), + len(psutil.cpu_times(percpu=True))) + def test_cpu_freq(self): w = wmi.WMI() proc = w.Win32_Processor()[0] self.assertEqual(proc.CurrentClockSpeed, psutil.cpu_freq().current) self.assertEqual(proc.MaxClockSpeed, psutil.cpu_freq().max) + +@unittest.skipIf(not WINDOWS, "WINDOWS only") +class TestSystemAPIs(unittest.TestCase): + + def test_nic_names(self): + out = sh('ipconfig /all') + nics = psutil.net_io_counters(pernic=True).keys() + for nic in nics: + if "pseudo-interface" in nic.replace(' ', '-').lower(): + continue + if nic not in out: + self.fail( + "%r nic wasn't found in 'ipconfig /all' output" % nic) + def test_total_phymem(self): w = wmi.WMI().Win32_ComputerSystem()[0] self.assertEqual(int(w.TotalPhysicalMemory), |