This class asynchronously reads the performance counters to calculate the system load on Windows. A "raw" thread is used here to prevent interference with the test suite's cases for the threading module.
| 17 | |
| 18 | |
| 19 | class WindowsLoadTracker(): |
| 20 | """ |
| 21 | This class asynchronously reads the performance counters to calculate |
| 22 | the system load on Windows. A "raw" thread is used here to prevent |
| 23 | interference with the test suite's cases for the threading module. |
| 24 | """ |
| 25 | |
| 26 | def __init__(self): |
| 27 | # make __del__ not fail if pre-flight test fails |
| 28 | self._running = None |
| 29 | self._stopped = None |
| 30 | |
| 31 | # Pre-flight test for access to the performance data; |
| 32 | # `PermissionError` will be raised if not allowed |
| 33 | winreg.QueryInfoKey(winreg.HKEY_PERFORMANCE_DATA) |
| 34 | |
| 35 | self._values = [] |
| 36 | self._load = None |
| 37 | self._running = _overlapped.CreateEvent(None, True, False, None) |
| 38 | self._stopped = _overlapped.CreateEvent(None, True, False, None) |
| 39 | |
| 40 | _thread.start_new_thread(self._update_load, (), {}) |
| 41 | |
| 42 | def _update_load(self, |
| 43 | # localize module access to prevent shutdown errors |
| 44 | _wait=_winapi.WaitForSingleObject, |
| 45 | _signal=_overlapped.SetEvent): |
| 46 | # run until signaled to stop |
| 47 | while _wait(self._running, 1000): |
| 48 | self._calculate_load() |
| 49 | # notify stopped |
| 50 | _signal(self._stopped) |
| 51 | |
| 52 | def _calculate_load(self, |
| 53 | # localize module access to prevent shutdown errors |
| 54 | _query=winreg.QueryValueEx, |
| 55 | _hkey=winreg.HKEY_PERFORMANCE_DATA, |
| 56 | _unpack=struct.unpack_from): |
| 57 | # get the 'System' object |
| 58 | data, _ = _query(_hkey, '2') |
| 59 | # PERF_DATA_BLOCK { |
| 60 | # WCHAR Signature[4] 8 + |
| 61 | # DWOWD LittleEndian 4 + |
| 62 | # DWORD Version 4 + |
| 63 | # DWORD Revision 4 + |
| 64 | # DWORD TotalByteLength 4 + |
| 65 | # DWORD HeaderLength = 24 byte offset |
| 66 | # ... |
| 67 | # } |
| 68 | obj_start, = _unpack('L', data, 24) |
| 69 | # PERF_OBJECT_TYPE { |
| 70 | # DWORD TotalByteLength |
| 71 | # DWORD DefinitionLength |
| 72 | # DWORD HeaderLength |
| 73 | # ... |
| 74 | # } |
| 75 | data_start, defn_start = _unpack('4xLL', data, obj_start) |
| 76 | data_base = obj_start + data_start |
no outgoing calls
no test coverage detected
searching dependent graphs…