Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   AutoIt (http://forum.oszone.net/forumdisplay.php?f=103)
-   -   [решено] Проблема: Рост потребляемой памяти при работе с WMI. (http://forum.oszone.net/showthread.php?t=152422)

timsky 05-10-2009 22:58 1235339

Проблема: Рост потребляемой памяти при работе с 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



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

Creat0R 06-10-2009 05:09 1235517

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

Код:

#include <Array.au3>

$aOwners = _ProcessesGetOwner('svchost.exe')

_ArrayDisplay($aOwners)

Func _ProcessesGetOwner($sPID_Name, $sComputer = ".")
    Local $objWMI, $colProcs, $sUserName, $sUserDomain, $aRet_Owners[1][2]

    $objWMI = ObjGet("winmgmts:\\" & $sComputer & "\root\cimv2")
    If Not IsObj($objWMI) Then Return SetError(1, 0, 0)

    $colProcs = $objWMI.ExecQuery("SELECT * FROM Win32_Process", "WQL", 0x30)
    If Not IsObj($colProcs) Then Return SetError(2, 0, 0)

    For $iProc In $colProcs
        If $iProc.Caption = $sPID_Name Then
            If $iProc.GetOwner($sUserName, $sUserDomain) Then ContinueLoop

            $aRet_Owners[0][0] += 1
            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
    Next

    Return $aRet_Owners
EndFunc


timsky 06-10-2009 07:05 1235534

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

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

SyDr 06-10-2009 07:42 1235538

Создай сам объект вне функции. И пропиши его в качестве параметра для функции.

timsky 06-10-2009 21:32 1236199

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 1236513

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

читать дальше »
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект
Создать объект
Получить данные
Унижтожить объект

читать дальше »
Создать объект
Получить данные
Получить данные
Получить данные
Получить данные
Получить данные
Унижтожить объект

Какой вариант использовать - решать тебе :)

Sp01LeR 07-10-2009 16:15 1236902

Цитата:

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

timsky 08-10-2009 06:03 1237390

SyDr,
Цитата:

Цитата SyDr
Вторым вариантом могу предложить обнулять переменную-объект перед выходом из функции. Вроде бы так тоже можно избавиться от роста потребляемой памяти. »

Пробовал, бесполезно. Помогло именно твое первое решение.


Время: 00:07.

Время: 00:07.
© OSzone.net 2001-