Script WSH: limitare il consumo di CPU
Eseguendo via WSH pesanti interrogazioni su Database o File System ho notato che entrambi i motori (cscript/wscript) tendono a consumare moltissima CPU (fino al 100%!) rubando preziose risorse anche ad alcuni processi prioritari e causando quindi pesanti rallenamenti nell'esecuzione del sistema e dei servizi.
Per ovviare a questo problema in passato ho cercato di "rallentare" in maniera artificiale l'esecuzione degli script inserendo alcuni "sleep" all'interno del codice sorgente.
Se pur questa non fosse una soluzione molto elegante si è rivelata piuttosto efficace ed estremamente facile da implementare, l'unica pecca era rappresentata dal fatto di dover spesso accettare tempi di esecuzione "allungati" dalle pause forzate delle istruzioni "sleep".
Di recente, durante la realizzazione di un nuovo progetto, ho sentito il bisogno di trovare un metodo migliore del precedente per rendere gli script meno aggressivi sulle risorse del sistema, ecco come ho fatto:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | Dim objWMI, objProc, ColProcs If LCase(Right(WScript.FullName, 11)) = "cscript.exe" Then Set objWMI = GetObject("winmgmts:\\.\root\cimv2") Set ColProcs = objWMI.ExecQuery("SELECT * FROM Win32_Process WHERE Name='cscript.exe'") For Each objProc in ColProcs If (InStr(LCase(objProc.CommandLine), LCase(WScript.ScriptName)) > 0) Then objProc.SetPriority 64 End If Next Set objWMI = Nothing Else Set objWMI = GetObject("winmgmts:\\.\root\cimv2") Set ColProcs = objWMI.ExecQuery("SELECT * FROM Win32_Process WHERE Name='wscript.exe'") For Each objProc in ColProcs If (InStr(LCase(objProc.CommandLine), LCase(WScript.ScriptName)) > 0) Then objProc.SetPriority 64 End If Next Set objWMI = Nothing End If |
Inserendo questo codice all'inizio di qualsiasi script si può fare in modo che il processo incaricato di eseguirlo abbia, nel sistema, la minor priorità possibile.
L'unica nota dolente di questo approccio basato su WMI è che non funziona su Windows 2000 poiché la proprietà "CommandLine" della classe "Win32_Process" è stata introdotta da Windows XP.
Per evitare il verificarsi di errori su Windows 2000 vi consiglio di arricchirlo con una funzione in grado di discriminare la versione del sistema operativo, ad esempio:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | Dim objWMI, objProc, ColProcs If Not IsWin2000 Then If LCase(Right(WScript.FullName, 11)) = "cscript.exe" Then Set objWMI = GetObject("winmgmts:\\.\root\cimv2") Set ColProcs = objWMI.ExecQuery("SELECT * FROM Win32_Process WHERE Name='cscript.exe'") For Each objProc in ColProcs If (InStr(LCase(objProc.CommandLine), LCase(WScript.ScriptName)) > 0) Then objProc.SetPriority 64 End If Next Set objWMI = Nothing Else Set objWMI = GetObject("winmgmts:\\.\root\cimv2") Set ColProcs = objWMI.ExecQuery("SELECT * FROM Win32_Process WHERE Name='wscript.exe'") For Each objProc in ColProcs If (InStr(LCase(objProc.CommandLine), LCase(WScript.ScriptName)) > 0) Then objProc.SetPriority 64 End If Next Set objWMI = Nothing End If End If Function IsWin2000 Dim TmpObjWMI, TmpObjOS, TmpColOSs IsWin2000 = False Set TmpObjWMI = GetObject("winmgmts:\\.\root\cimv2") Set TmpColOSs = TmpObjWMI.ExecQuery ("Select * from Win32_OperatingSystem") For Each TmpObjOS in TmpColOSs If (Instr(LCase(TmpObjOS.Caption), Lcase("2000")) > 0) Then IsWin2000 = True End If Next Set TmpObjWMI = Nothing End Function |
Autore
Mirko Iodice
mirko -at- notageek (.dot) it
Print This • Email this • Twit This! • Add to del.icio.us • Share on Facebook • Digg This! • Stumble It! • AddThis! • Share on Segnalo Alice • Share on OKNotizie