Показать полную графическую версию : [решено] Проблема: Рост потребляемой памяти при работе с WMI.
Вот пример:
While 1
$aProcess = ProcessList('svchost.exe')
For $i = 1 To $aProcess[0][0]
_ProcessGetOwner($aProcess[$i][1])
Next
Sleep(10)
WEnd
Func _ProcessGetOwner($PID, $sComputer = ".")
Local $objWMI, $colProcs, $sUserName, $sUserDomain
$objWMI = ObjGet("winmgmts:\\" & $sComputer & "\root\cimv2")
If IsObj($objWMI) Then
$colProcs = $objWMI.ExecQuery("Select ProcessId From Win32_Process Where ProcessId="& $PID)
If IsObj($colProcs) Then
For $Proc In $colProcs
If $Proc.GetOwner($sUserName, $sUserDomain)=0 Then Return $sUserDomain & "\" & $sUserName
Next
EndIf
EndIf
EndFunc
Проблема в том, что со временем (в данном примере это видно уже через минуту) начинает расти потребление памяти.
Как этого избежать?
Вообще то не обязательно использовать столько циклов, просто переделываем функцию немного(?):
#include <Array.au3>
$aOwners = _ProcessesGetOwner('svchost.exe')
_ArrayDisplay($aOwners)
Func (http://www.autoitscript.com/autoit3/docs/keywords.htm#Func) _ProcessesGetOwner($sPID_Name, $sComputer = ".")
Local (http://www.autoitscript.com/autoit3/docs/keywords.htm#Local) $objWMI, $colProcs, $sUserName, $sUserDomain, $aRet_Owners[1][2]
$objWMI = ObjGet (http://www.autoitscript.com/autoit3/docs/functions/ObjGet.htm)("winmgmts:\\" & $sComputer & "\root\cimv2")
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) Not (http://www.autoitscript.com/autoit3/docs/keywords.htm#Not) IsObj (http://www.autoitscript.com/autoit3/docs/functions/IsObj.htm)($objWMI) Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) Return (http://www.autoitscript.com/autoit3/docs/keywords.htm#Return) SetError (http://www.autoitscript.com/autoit3/docs/functions/SetError.htm)(1, 0, 0)
$colProcs = $objWMI.ExecQuery("SELECT * FROM Win32_Process", "WQL", 0x30)
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) Not (http://www.autoitscript.com/autoit3/docs/keywords.htm#Not) IsObj (http://www.autoitscript.com/autoit3/docs/functions/IsObj.htm)($colProcs) Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) Return (http://www.autoitscript.com/autoit3/docs/keywords.htm#Return) SetError (http://www.autoitscript.com/autoit3/docs/functions/SetError.htm)(2, 0, 0)
For (http://www.autoitscript.com/autoit3/docs/keywords.htm#For) $iProc In (http://www.autoitscript.com/autoit3/docs/keywords.htm#In) $colProcs
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) $iProc.Caption = $sPID_Name Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then)
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) $iProc.GetOwner($sUserName, $sUserDomain) Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) ContinueLoop (http://www.autoitscript.com/autoit3/docs/keywords.htm#ContinueLoop)
$aRet_Owners[0][0] += 1
ReDim (http://www.autoitscript.com/autoit3/docs/keywords.htm#ReDim) $aRet_Owners[$aRet_Owners[0][0]+1][2]
$aRet_Owners[$aRet_Owners[0][0]][0] = $iProc.ProcessID
$aRet_Owners[$aRet_Owners[0][0]][1] = $sUserDomain & "\" & $sUserName
EndIf (http://www.autoitscript.com/autoit3/docs/keywords.htm#EndIf)
Next (http://www.autoitscript.com/autoit3/docs/keywords.htm#Next)
Return (http://www.autoitscript.com/autoit3/docs/keywords.htm#Return) $aRet_Owners
EndFunc (http://www.autoitscript.com/autoit3/docs/keywords.htm#EndFunc)
Спасибо за исправленный вариант, но проблема в том, что если процесс периодически выполняет ф-ю _ProcessesGetOwner() (например, как в моем примере выше сунуть для наглядности в бесколечный луп), то объем занимаемой памяти неуклонно растет. И чем меньше слип, тем быстрее.
У меня на серваке крутится скрипт, который через пол дня начинает заметно жрать память. Бывало, что по несколько сотен метров, если его не перезапускать.
Создай сам объект вне функции. И пропиши его в качестве параметра для функции.
SyDr, Точно! Помогло.
А с чем сей косяк связан?
Вот пример, если кому не понятно будет:
$objWMI = ObjGet("winmgmts:\\.\root\cimv2")
While 1
$aProcess = ProcessList('svchost.exe')
For $i = 1 To $aProcess[0][0]
_ProcessGetOwner($aProcess[$i][1])
Next
Sleep(10)
WEnd
Func _ProcessGetOwner($PID)
Local $colProcs, $sUserName, $sUserDomain
If IsObj($objWMI) Then
$colProcs = $objWMI.ExecQuery("Select ProcessId From Win32_Process Where ProcessId="& $PID)
If IsObj($colProcs) Then
For $Proc In $colProcs
If $Proc.GetOwner($sUserName, $sUserDomain)=0 Then Return $sUserDomain & "\" & $sUserName
Next
EndIf
EndIf
EndFunc
Скорее всего с тем, что сам объект всё ещё остаётся в памяти. Ты каждый раз при вызове функции создаёшь новый объект. Однако, похоже, что даже если он является локальным - после выхода из функции он не уничтожается. Вторым вариантом могу предложить обнулять переменную-объект перед выходом из функции. Вроде бы так тоже можно избавиться от роста потребляемой памяти. Поправьте меня, если я не прав. Однако, если объект испольузется больше двух раз - зачем постоянно создавать новый?
По русски всё выглядит так (ну, допустим, ты используешь объект 5 раз):
Создать объект
Получить данные
Создать объект
Получить данные
Создать объект
Получить данные
Создать объект
Получить данные
Создать объект
Получить данные
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Получить данные
Получить данные
Получить данные
Получить данные
Унижтожить объект
Какой вариант использовать - решать тебе :)
А с чем сей косяк связан?
Я думаю, что косяк связан с запросом в базу для локального обьекта $objWMI (каждый запрос создает новый обьект)...
Интересно, какой будет результат, если $colProcs тоже сделать глобальным? :)
SyDr, Вторым вариантом могу предложить обнулять переменную-объект перед выходом из функции. Вроде бы так тоже можно избавиться от роста потребляемой памяти. »
Пробовал, бесполезно. Помогло именно твое первое решение.
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.
Available in ZeroNet 1osznRoVratMCN3bFoFpR2pSV5c9z6sTC