PDA

Показать полную графическую версию : [решено] Проблема: Рост потребляемой памяти при работе с WMI.


timsky
05-10-2009, 22:58
Вот пример:
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

Проблема в том, что со временем (в данном примере это видно уже через минуту) начинает расти потребление памяти.
Как этого избежать?

Creat0R
06-10-2009, 05:09
Вообще то не обязательно использовать столько циклов, просто переделываем функцию немного(?):

#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)

timsky
06-10-2009, 07:05
Спасибо за исправленный вариант, но проблема в том, что если процесс периодически выполняет ф-ю _ProcessesGetOwner() (например, как в моем примере выше сунуть для наглядности в бесколечный луп), то объем занимаемой памяти неуклонно растет. И чем меньше слип, тем быстрее.

У меня на серваке крутится скрипт, который через пол дня начинает заметно жрать память. Бывало, что по несколько сотен метров, если его не перезапускать.

SyDr
06-10-2009, 07:42
Создай сам объект вне функции. И пропиши его в качестве параметра для функции.

timsky
06-10-2009, 21:32
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

SyDr
07-10-2009, 08:30
Скорее всего с тем, что сам объект всё ещё остаётся в памяти. Ты каждый раз при вызове функции создаёшь новый объект. Однако, похоже, что даже если он является локальным - после выхода из функции он не уничтожается. Вторым вариантом могу предложить обнулять переменную-объект перед выходом из функции. Вроде бы так тоже можно избавиться от роста потребляемой памяти. Поправьте меня, если я не прав. Однако, если объект испольузется больше двух раз - зачем постоянно создавать новый?
По русски всё выглядит так (ну, допустим, ты используешь объект 5 раз):
Создать объект
Получить данные
Создать объект
Получить данные
Создать объект
Получить данные
Создать объект
Получить данные
Создать объект
Получить данные
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Получить данные
Получить данные
Получить данные
Получить данные
Унижтожить объект
Какой вариант использовать - решать тебе :)

Sp01LeR
07-10-2009, 16:15
А с чем сей косяк связан?

Я думаю, что косяк связан с запросом в базу для локального обьекта $objWMI (каждый запрос создает новый обьект)...
Интересно, какой будет результат, если $colProcs тоже сделать глобальным? :)

timsky
08-10-2009, 06:03
SyDr, Вторым вариантом могу предложить обнулять переменную-объект перед выходом из функции. Вроде бы так тоже можно избавиться от роста потребляемой памяти. »
Пробовал, бесполезно. Помогло именно твое первое решение.




© OSzone.net 2001-2012