import sys import threading import ctypes from ctypes import byref from ctypes import Structure, Union from ctypes.wintypes import * # other wintype definition LPVOID = ctypes.c_void_p LPCVOID = LPVOID DWORD_PTR = DWORD LONGLONG = ctypes.c_longlong HCOUNTER = HQUERY = HANDLE # error code Error_Success = 0 # macro sleep = ctypes.windll.kernel32.Sleep pdh = ctypes.windll.pdh # structure definition class Sysinfo_Struct(Structure): _fields_ = [('wProcessorArchitecture', WORD), ('wReserved', WORD)] class Sysinfo_Union(Union): _fields_ = [('dwOemId', DWORD), ('struct', Sysinfo_Struct)] class System_Info(Structure): _fields_ = [('union', Sysinfo_Union), ('dwPageSize', DWORD), ('lpMinimumApplicationAddress', LPVOID), ('lpMaximumApplicationAddress', LPVOID), ('dwActiveProcessorMask', DWORD_PTR), ('dwNumberOfProcessors', DWORD), ('dwProcessorType', DWORD), ('dwAllocationGranularity', DWORD), ('wProcessorLevel', WORD), ('wProcessorRevision', WORD)] class PDH_Counter_Union(Union): _fields_ = [('longValue', LONG), ('doubleValue', ctypes.c_double), ('largeValue', LONGLONG), ('AnsiStringValue', LPCSTR), ('WideStringValue', LPCWSTR)] class PDH_FMT_COUNTERVALUE(Structure): _fields_ = [('CStatus', DWORD), ('union', PDH_Counter_Union),] # Exception definition class TargetRateExceedError(Exception): pass def getProcessorNumber(): si = System_Info() ctypes.windll.kernel32.GetSystemInfo(byref(si)) return si.dwNumberOfProcessors g_cpu_usage = 0 class QueryCPUUsageThread(threading.Thread): def __init__(self): super(QueryCPUUsageThread, self).__init__() self.hQuery = HQUERY() self.hCounter = HCOUNTER() if not pdh.PdhOpenQueryW(None, 0, byref(self.hQuery)) == Error_Success: raise RuntimeError('[QueryCPUUsageThread] Open query failed') if not pdh.PdhAddCounterW(self.hQuery, u'''\\Processor(_Total)\\% Processor Time''', 0, byref(self.hCounter)) == Error_Success: raise RuntimeError('[QueryCPUUsageThread] Add counter failed') def run(self): while True: usage = self.getCPUUsage() global g_cpu_usage g_cpu_usage = usage def getCPUUsage(self): if not pdh.PdhCollectQueryData(self.hQuery) == Error_Success: raise RuntimeError('[QueryCPUUsageThread] CollectQueryData failed') ctypes.windll.kernel32.Sleep(1000) if not pdh.PdhCollectQueryData(self.hQuery) == Error_Success: raise RuntimeError('[QueryCPUUsageThread] CollectQueryData failed') dwType = DWORD(0) value = PDH_FMT_COUNTERVALUE() if not pdh.PdhGetFormattedCounterValue(self.hCounter, 0x00000100, # PDH_FMT_LONG byref(dwType), byref(value)) == Error_Success: raise RuntimeError('[QueryCPUUsageThread] Get CounterValue failed') return value.union.longValue def main(targetRateForMainProcess, targetRate): timeInterval = 50.0 busyTime = float(targetRateForMainProcess) * timeInterval / 100.0 idleTime = timeInterval - busyTime TOLERANCE = 2 while True: if len(sys.argv)<=1: usage = g_cpu_usage if abs(usage - targetRate) < TOLERANCE: pass elif usage > targetRate: busyTime = max(busyTime - 0.1, 1) idleTime = timeInterval - busyTime else: busyTime = min(busyTime + 0.1, 49) idleTime = timeInterval - busyTime #print busyTime, idleTime startTime = ctypes.windll.kernel32.GetTickCount() while ctypes.windll.kernel32.GetTickCount() - startTime < int(round(busyTime)): pass sleep(int(round(idleTime))) def subpMain(): while True: pass def inputLoop(): while True: print 'please input target cpu usage: ', try: rate = float(raw_input().strip()) if rate >= 100 or rate <=1: raise TargetRateExceedError except TargetRateExceedError: print 'please input a number in range 1-99' except Exception: print 'please input a target cpu usage rate, e.g. 70' else: return rate if __name__=='__main__': if len(sys.argv) <= 1: # main process targetRate = inputLoop() nProcessor = getProcessorNumber() fullPercentPerProcessor = 100.0 / float(nProcessor) targetRateForMainProcess = targetRate while targetRateForMainProcess > fullPercentPerProcessor: from subprocess import Popen obj=Popen([sys.executable, __file__, 'child']) targetRateForMainProcess -= fullPercentPerProcessor queryCpuThread = QueryCPUUsageThread() queryCpuThread.start() main(targetRateForMainProcess, targetRate) else: # subprocess subpMain()