Find and eliminate memory leaks
-
Recently Browsing 0 members
No registered users viewing this page.
-
Similar Content
-
By rudi
@guinness mentioned in a different thread an Approach, I honestly do not 100% how to use it.
I have a script, that shall run on one Windows box only once.
If started more than once, it shall not Exit itself, but kill the other processes using the same _Singleton "$sOccurrenceName".
So what I would Need is the PID(s) of the *OTHER* instances, that use the same "$sOccurrenceName". This may be from a different logon ("global\"), and the @scriptname might be different, too. (someone might rename the EXE, for what sensless reason whatsoever...)
TIA, Rudi.
-
By Arlen
I think I have memory leak issue...
Every time I use _IENavigate() my Memory Ram goes up and never down.. I could reach 1gb just using this function. Which is weird..
#include <IE.au3> #include <GUIConstantsEx.au3> #RequireAdmin Global $oIE = _IECreateEmbedded() Global $Form1 = GUICreate("Form1", 920, 466, 502, 342) GUICtrlCreateObj($oIE, 8, 72, 897, 370) ;IE OBJ Local $Button1 = GUICtrlCreateButton("FETCH", 808, 8, 91, 57) GUISetState(@SW_SHOW) While 1 Local $nMsg = GUIGetMsg() Switch $nMsg Case $GUI_EVENT_CLOSE Exit Case $Button1 Fetch() EndSwitch WEnd Func Fetch() For $i = 0 To 20 _IENavigate($oIE, 'https://www.google.com/search?source=hp&ei=hzprXM_zN-zs_QbExry4CQ&q=sad&btnK=Google+Search&oq=&gs_l=psy-ab.3..35i39j0i67l9.2993.3926..4083...1.0..0.137.749.0j6......0....1..gws-wiz.....6.eVCDaXHQXYA') Next EndFunc
-
By argumentum
I was asking around on how to detect memory leaks and came up with a logger ( or just stop execution, or restart ).
Here is the code. ( should have done a UDF but maybe there is no need for such )
#AutoIt3Wrapper_Au3Check_Parameters=-q -d -w 1 -w 2 -w 3 -w 4 -w 6 -w 7 #include <SQLite.au3> #include <WinAPISys.au3> #include <WinAPIProc.au3> #include <Date.au3> #include <Array.au3>; For _ArrayDisplay() Example() Func Example() ConsoleWrite(MemLeakTooMuch() & @CRLF) ; call once at first to initialize the baseline. Local $a = MemLeakLog(1) ; ..you could call this on the fly and get an array _ArrayDisplay($a) ; call on AdlibRegister() or other means ; Ex: AdlibRegister("OnMemLeakRestart", 3600000) ; once an hour ; While Sleep(50) ; ... ... ; WEnd EndFunc ;==>Example #Region MemLeak Func OnMemLeakRestart() ; Local Static $iTriggered = 0 If MemLeakTooMuch() Then If Not $iTriggered Then $iTriggered = 1 AdlibRegister("OnMemLeakRestart", 60000) ; since it triggered, check more often EndIf If _WinAPI_GetIdleTime() > 600000 Then ; over 10 min. maybe ?, to not bother the user ? ShellExecute(@ScriptFullPath) ; restart itself if it must, but if you do, ; keep that in mind while coding. Exit 3 ; use the exit code you please other than 1 or 2, EndIf ; as AutoIt may use it for itself. EndIf EndFunc ;==>OnMemLeakRestart Func MemLeakLog($ReturnAnArray = 0) Local $aMethod[5] = ["EXITCLOSE_NORMAL", "EXITCLOSE_BYEXIT", "EXITCLOSE_BYCLICK", "EXITCLOSE_BYLOGOFF", "EXITCLOSE_BYSHUTDOWN"] Local $iMethod = Execute("@exitMethod") Local $aDesc[14] = ["number of page faults", "peak working set size, in bytes", "current working set size, in bytes", _ "peak paged pool usage, in bytes", "current paged pool usage, in bytes", "peak nonpaged pool usage, in bytes", _ "current nonpaged pool usage, in bytes", "current space allocated for the pagefile, in bytes", _ "peak space allocated for the pagefile, in bytes", "current amount of memory that cannot be shared with other processes, in bytes", _ "ProcessHandleCount", "ProcessThreadsCount", "GDI objects", "USER objects"] Local $s = @YEAR & "." & @MON & "." & @MDAY & "_" & @HOUR & ":" & @MIN & ":" & @SEC $s &= " - RunTime: " & _Convert(gTimer()) & " - PID: " & @AutoItPID If IsInt($iMethod) Then $s &= " - ExitCode: " & @exitCode $s &= " - ExitMethod: " & $iMethod & " (" & $aMethod[$iMethod] & ")" EndIf Local $a[4][15] $a[1][0] = "Starting:" $a[2][0] = " Exiting:" $a[3][0] = " Diff.:" MemLeakTooMuch() Local $b = MemLeakTooMuch(-2), $c = MemLeakTooMuch(-3) For $n = 0 To UBound($c) - 1 $a[0][$n + 1] = $aDesc[$n] $a[1][$n + 1] = $b[$n] $a[2][$n + 1] = $c[$n] $a[3][$n + 1] = $c[$n] - $b[$n] Switch $n Case 0, 10, 11, 12, 13, 14 ; nothing, is a count number Case Else $a[3][$n + 1] = ByteSuffix($a[3][$n + 1]) EndSwitch $a[3][$n + 1] &= " ( x" & (($b[$n] > 0 And $b[$n] > 0) ? Round($c[$n] / $b[$n], 1) : "1") & " )" Next If Int(Eval("ReturnAnArray")) Then $a[0][0] = _Convert(gTimer()) Return $a Else FileWriteLine(StringTrimRight(@ScriptFullPath, 4) & ".ProcessInfo.log", $s & @CRLF & _ _SQLite_Display2DResult($a, 0, True) & Eval("sErrorHandler") & @CRLF) ; I save the data from ObjEvent("AutoIt.Error", "_ErrFunc") to $sErrorHandler EndIf EndFunc ;==>MemLeakLog Func MemLeakTooMuch($iPid = 0, $iMutliplier = 4) ; in case this is for some other PID, but only one =/ Local Static $aInitProcessMemoryInfo = 99, $aLastProcessMemoryInfo Local $ret = False, $a, $n, $aTemp If $iPid = -2 Then Return $aInitProcessMemoryInfo ; returns the initial readings If $iPid = -3 Then Return $aLastProcessMemoryInfo ; returns the last readings If $aInitProcessMemoryInfo = 99 Then $aTemp = _WinAPI_GetProcessMemoryInfo($iPid) If Not (UBound($aTemp) = 10) Then Return SetError(1, 0, $ret) $aLastProcessMemoryInfo = $aTemp Else $aTemp = _WinAPI_GetProcessMemoryInfo($iPid) If Not (UBound($aTemp) = 10) Then Return SetError(1, 0, $ret) $aLastProcessMemoryInfo = $aTemp For $n = 1 To UBound($aTemp) - 1 ; I don't think "page faults" is leakage, so it's omited. If $aTemp[$n] > $aInitProcessMemoryInfo[$n] * $iMutliplier Then $ret = True Next EndIf ReDim $aLastProcessMemoryInfo[14] ; to hold the next values $aLastProcessMemoryInfo[10] = _WinAPI_GetProcessHandleCount($iPid) If $aLastProcessMemoryInfo[10] > 2000 Then $ret = True ; dropping handles ? $a = _WinAPI_EnumProcessThreads($iPid) $aLastProcessMemoryInfo[11] = UBound($a) - 1 If $aLastProcessMemoryInfo[11] > 200 Then $ret = True ; dropping threads ? If Not $iPid Then $iPid = -1 $aLastProcessMemoryInfo[12] = _WinAPI_GetGuiResources(0, $iPid) ; count of GDI objects. $aLastProcessMemoryInfo[13] = _WinAPI_GetGuiResources(1, $iPid) ; count of USER objects If $aLastProcessMemoryInfo[12] > 1000 Then $ret = True ; dropping GDI objects ? If $aLastProcessMemoryInfo[13] > 2000 Then $ret = True ; dropping USER objects ? If $aInitProcessMemoryInfo = 99 Then gTimer() ; init. the timer now, if was not at the top of the script $aInitProcessMemoryInfo = $aLastProcessMemoryInfo OnAutoItExitRegister("MemLeakLog") ; ..if you wanna keep a log EndIf Return $ret EndFunc ;==>MemLeakTooMuch Func _Convert($ms) ; https://www.autoitscript.com/forum/topic/163621-convert-ms-to-dayhourminsec/?do=findComment&comment=1192334 Local $day, $hour, $min, $sec _TicksToTime($ms, $hour, $min, $sec) If $hour > 24 Then $day = $hour / 24 $hour = Mod($hour, 24) EndIf Return StringReplace(StringFormat("%03i %02i:%02i:%02i", $day, $hour, $min, $sec), "000 ", "") EndFunc ;==>_Convert Func gTimer() Local Static $Timer = TimerInit() Return TimerDiff($Timer) EndFunc ;==>gTimer Func ByteSuffix($iBytes) ; https://www.autoitscript.com/autoit3/docs/functions/FileGetSize.htm Local $iIndex = 0, $aArray = [' bytes', ' KB', ' MB', ' GB', ' TB', ' PB', ' EB', ' ZB', ' YB'] While $iBytes > 1023 $iIndex += 1 $iBytes /= 1024 WEnd Return Round($iBytes) & $aArray[$iIndex] EndFunc ;==>ByteSuffix #EndRegion MemLeak I'm gonna use it for a pain in the neck script.
If you find ways to improve it, or something I missed, let me know.
2019.01.05 update: Added GDI objects and USER objects. Added return array. Fixed boo-boo. Added Diff. multiplier.
-
By argumentum
How do I know there is a memory leak ?, is it "Private Bytes" or "Working Set" too ?
I have some clues but no definitive knowing. I have no experience looking at these.
Also, If I can use AutoIt to self-check within the code would be most helpful.
Thanks
-
By ur
I have used _Singleton function in my script to restrict only one instance to run.
For testing, I have written below code, and triggered multiple instances.
#include <Misc.au3> MsgBox(0,"",@ScriptName) if _Singleton(@ScriptName, 1) = 0 Then Msgbox(64, @ScriptName, "The program is already running.") Exit Else MsgBox(0,@ScriptName,"No other instances running") EndIf But all are going to else block.
Please suggest.
-
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now