diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2016-03-05 11:00:44 -0800 |
---|---|---|
committer | Giampaolo Rodola <g.rodola@gmail.com> | 2016-03-05 11:00:44 -0800 |
commit | 2255b1285ed9577f79f0b83a1e9b5fb6400f9464 (patch) | |
tree | e45e5ec96507752d7dc143717ff07e5c7f48fa0f | |
parent | 77386f15f2c83895c6ba97e10fc35ffe92a02f56 (diff) | |
download | psutil-2255b1285ed9577f79f0b83a1e9b5fb6400f9464.tar.gz |
#792 / cpu_stats: win impl
-rw-r--r-- | docs/index.rst | 24 | ||||
-rw-r--r-- | psutil/_psutil_windows.c | 125 | ||||
-rw-r--r-- | psutil/_pswindows.py | 9 | ||||
-rw-r--r-- | psutil/arch/windows/ntextapi.h | 89 |
4 files changed, 241 insertions, 6 deletions
diff --git a/docs/index.rst b/docs/index.rst index 6fd3dfa5..b8ff418e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -155,18 +155,16 @@ CPU Return various CPU statistics as a namedtuple whose fields change depending on the platform. - ctx_switches, interrupts, soft_interrupts, syscalls, traps - +-----------------+-----------------+--------------+-----------------+-----------------+-----------------+--------------+ | Linux | OSX | Windows | FreeBSD | OpenBSD | NetBSD | SunOS | +=================+=================+==============+=================+=================+=================+==============+ - | ctx_switches | ctx_switches | | ctx_switches | ctx_switches | ctx_switches | ctx_switches | + | ctx_switches | ctx_switches | ctx_switches | ctx_switches | ctx_switches | ctx_switches | ctx_switches | +-----------------+-----------------+--------------+-----------------+-----------------+-----------------+--------------+ - | interrupts | interrupts | | interrupts | interrupts | interrupts | interrupts | + | interrupts | interrupts | interrupts | interrupts | interrupts | interrupts | interrupts | +-----------------+-----------------+--------------+-----------------+-----------------+-----------------+--------------+ - | soft_interrupts | soft_interrupts | | soft_interrupts | soft_interrupts | soft_interrupts | syscalls | + | soft_interrupts | soft_interrupts | dpcs | soft_interrupts | soft_interrupts | soft_interrupts | syscalls | +-----------------+-----------------+--------------+-----------------+-----------------+-----------------+--------------+ - | procs_running | syscalls | | syscalls | syscalls | syscalls | traps | + | procs_running | syscalls | syscalls | syscalls | syscalls | syscalls | traps | +-----------------+-----------------+--------------+-----------------+-----------------+-----------------+--------------+ | procs_blocked | traps | | traps | traps | traps | | +-----------------+-----------------+--------------+-----------------+-----------------+-----------------+--------------+ @@ -177,6 +175,20 @@ CPU | | | | | | | | +-----------------+-----------------+--------------+-----------------+-----------------+-----------------+--------------+ + - **ctx_switches**: + number of context switches (voluntary + involuntary) since boot. + - **interrupts**: + number of interrupts since boot. + - **interrupts**: + number of software interrupts since boot. + - **syscalls**: number of system calls since boot. + - **traps**: number of kernel traps since boot. + - **dpcs** *(Windows)*: number of + `delayed procedure calls <https://technet.microsoft.com/en-us/library/cc938646.aspx>`__ + since boot. + - **procs_running** *(Linux)*: current number of actively running processes. + - **procs_blocked** *(Linux)*: current number of processes waiting for I/O. + Example (Linux): .. code-block:: python diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c index 05ad39d5..54a3a5d3 100644 --- a/psutil/_psutil_windows.c +++ b/psutil/_psutil_windows.c @@ -3119,6 +3119,129 @@ error: } +/* + * Return CPU statistics. + */ +static PyObject * +psutil_cpu_stats(PyObject *self, PyObject *args) { + // NtQuerySystemInformation stuff + typedef DWORD (_stdcall * NTQSI_PROC) (int, PVOID, ULONG, PULONG); + NTQSI_PROC NtQuerySystemInformation; + HINSTANCE hNtDll; + + NTSTATUS status; + _SYSTEM_PERFORMANCE_INFORMATION *spi = NULL; + _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL; + _SYSTEM_INTERRUPT_INFORMATION *InterruptInformation = NULL; + SYSTEM_INFO si; + UINT i; + ULONG64 dpcs = 0; + ULONG interrupts = 0; + + // obtain NtQuerySystemInformation + hNtDll = LoadLibrary(TEXT("ntdll.dll")); + if (hNtDll == NULL) { + PyErr_SetFromWindowsErr(0); + goto error; + } + NtQuerySystemInformation = (NTQSI_PROC)GetProcAddress( + hNtDll, "NtQuerySystemInformation"); + if (NtQuerySystemInformation == NULL) { + PyErr_SetFromWindowsErr(0); + goto error; + } + + // retrives number of processors + GetSystemInfo(&si); + + // get syscalls / ctx switches + spi = (_SYSTEM_PERFORMANCE_INFORMATION *) \ + malloc(si.dwNumberOfProcessors * \ + sizeof(_SYSTEM_PERFORMANCE_INFORMATION)); + if (spi == NULL) { + PyErr_NoMemory(); + goto error; + } + status = NtQuerySystemInformation( + SystemPerformanceInformation, + spi, + si.dwNumberOfProcessors * sizeof(_SYSTEM_PERFORMANCE_INFORMATION), + NULL); + if (status != 0) { + PyErr_SetFromWindowsErr(0); + goto error; + } + + // get DPCs + InterruptInformation = \ + malloc(sizeof(_SYSTEM_INTERRUPT_INFORMATION) * + si.dwNumberOfProcessors); + if (InterruptInformation == NULL) { + PyErr_NoMemory(); + goto error; + } + status = NtQuerySystemInformation( + SystemInterruptInformation, + InterruptInformation, + si.dwNumberOfProcessors * sizeof(SYSTEM_INTERRUPT_INFORMATION), + NULL); + if (status != 0) { + PyErr_SetFromWindowsErr(0); + goto error; + } + for (i = 0; i < si.dwNumberOfProcessors; i++) { + dpcs += InterruptInformation[i].DpcCount; + } + + // get interrupts + sppi = (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \ + malloc(si.dwNumberOfProcessors * \ + sizeof(_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); + if (sppi == NULL) { + PyErr_NoMemory(); + goto error; + } + + status = NtQuerySystemInformation( + SystemProcessorPerformanceInformation, + sppi, + si.dwNumberOfProcessors * sizeof + (_SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), + NULL); + if (status != 0) { + PyErr_SetFromWindowsErr(0); + goto error; + } + + for (i = 0; i < si.dwNumberOfProcessors; i++) { + interrupts += sppi[i].InterruptCount; + } + + + // done + free(spi); + free(InterruptInformation); + FreeLibrary(hNtDll); + return Py_BuildValue( + "kkkk", + spi->ContextSwitches, + interrupts, + (unsigned long)dpcs, + spi->SystemCalls + ); + +error: + if (spi) + free(spi); + if (InterruptInformation) + free(InterruptInformation); + if (hNtDll) + FreeLibrary(hNtDll); + return NULL; +} + + + // ------------------------ Python init --------------------------- static PyMethodDef @@ -3223,6 +3346,8 @@ PsutilMethods[] = { "Return NICs addresses."}, {"net_if_stats", psutil_net_if_stats, METH_VARARGS, "Return NICs stats."}, + {"cpu_stats", psutil_cpu_stats, METH_VARARGS, + "Return NICs stats."}, // --- windows API bindings {"win32_QueryDosDevice", psutil_win32_QueryDosDevice, METH_VARARGS, diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py index 4143afd7..731c2051 100644 --- a/psutil/_pswindows.py +++ b/psutil/_pswindows.py @@ -98,6 +98,9 @@ ntpinfo = namedtuple( 'ntpinfo', ['num_handles', 'ctx_switches', 'user_time', 'kernel_time', 'create_time', 'num_threads', 'io_rcount', 'io_wcount', 'io_rbytes', 'io_wbytes']) +ssysinfo = namedtuple( + 'ssysinfo', ['ctx_switches', 'interrupts', 'dpcs', 'syscalls']) + # set later from __init__.py NoSuchProcess = None @@ -209,6 +212,12 @@ def cpu_count_physical(): return cext.cpu_count_phys() +def cpu_stats(): + """Return CPU statistics.""" + ctx_switches, interrupts, dpcs, syscalls = cext.cpu_stats() + return ssysinfo(ctx_switches, interrupts, dpcs, syscalls) + + def boot_time(): """The system boot time expressed in seconds since the epoch.""" return cext.boot_time() diff --git a/psutil/arch/windows/ntextapi.h b/psutil/arch/windows/ntextapi.h index 7cfa6fa5..74adce22 100644 --- a/psutil/arch/windows/ntextapi.h +++ b/psutil/arch/windows/ntextapi.h @@ -18,6 +18,95 @@ typedef struct { } _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION; +typedef struct { + LARGE_INTEGER IdleProcessTime; + LARGE_INTEGER IoReadTransferCount; + LARGE_INTEGER IoWriteTransferCount; + LARGE_INTEGER IoOtherTransferCount; + ULONG IoReadOperationCount; + ULONG IoWriteOperationCount; + ULONG IoOtherOperationCount; + ULONG AvailablePages; + ULONG CommittedPages; + ULONG CommitLimit; + ULONG PeakCommitment; + ULONG PageFaultCount; + ULONG CopyOnWriteCount; + ULONG TransitionCount; + ULONG CacheTransitionCount; + ULONG DemandZeroCount; + ULONG PageReadCount; + ULONG PageReadIoCount; + ULONG CacheReadCount; + ULONG CacheIoCount; + ULONG DirtyPagesWriteCount; + ULONG DirtyWriteIoCount; + ULONG MappedPagesWriteCount; + ULONG MappedWriteIoCount; + ULONG PagedPoolPages; + ULONG NonPagedPoolPages; + ULONG PagedPoolAllocs; + ULONG PagedPoolFrees; + ULONG NonPagedPoolAllocs; + ULONG NonPagedPoolFrees; + ULONG FreeSystemPtes; + ULONG ResidentSystemCodePage; + ULONG TotalSystemDriverPages; + ULONG TotalSystemCodePages; + ULONG NonPagedPoolLookasideHits; + ULONG PagedPoolLookasideHits; + ULONG AvailablePagedPoolPages; + ULONG ResidentSystemCachePage; + ULONG ResidentPagedPoolPage; + ULONG ResidentSystemDriverPage; + ULONG CcFastReadNoWait; + ULONG CcFastReadWait; + ULONG CcFastReadResourceMiss; + ULONG CcFastReadNotPossible; + ULONG CcFastMdlReadNoWait; + ULONG CcFastMdlReadWait; + ULONG CcFastMdlReadResourceMiss; + ULONG CcFastMdlReadNotPossible; + ULONG CcMapDataNoWait; + ULONG CcMapDataWait; + ULONG CcMapDataNoWaitMiss; + ULONG CcMapDataWaitMiss; + ULONG CcPinMappedDataCount; + ULONG CcPinReadNoWait; + ULONG CcPinReadWait; + ULONG CcPinReadNoWaitMiss; + ULONG CcPinReadWaitMiss; + ULONG CcCopyReadNoWait; + ULONG CcCopyReadWait; + ULONG CcCopyReadNoWaitMiss; + ULONG CcCopyReadWaitMiss; + ULONG CcMdlReadNoWait; + ULONG CcMdlReadWait; + ULONG CcMdlReadNoWaitMiss; + ULONG CcMdlReadWaitMiss; + ULONG CcReadAheadIos; + ULONG CcLazyWriteIos; + ULONG CcLazyWritePages; + ULONG CcDataFlushes; + ULONG CcDataPages; + ULONG ContextSwitches; + ULONG FirstLevelTbFills; + ULONG SecondLevelTbFills; + ULONG SystemCalls; + +} _SYSTEM_PERFORMANCE_INFORMATION; + + +typedef struct { + ULONG ContextSwitches; + ULONG DpcCount; + ULONG DpcRate; + ULONG TimeIncrement; + ULONG DpcBypassCount; + ULONG ApcBypassCount; +} _SYSTEM_INTERRUPT_INFORMATION; + + typedef enum _KTHREAD_STATE { Initialized, Ready, |