Jump to content

_ReduceMemory UDF


jftuga
 Share

Recommended Posts

I really love AutoIt, but always thought that the scripts took up too much memory. One day I stumbled across empty.exe from the 2003 resource kit, which essentially frees unused memory from a process. I had this discussion and this one with Valik and w0uter which resulted in the UDF below. Basically, it uses all of w0uter's code :)

The results are spectacular -- usually a 50% reduction in memory with no noticable performance degradation. Memory usage, as reported by Task Manager, does grow over time, but not by that much.

I have attached the code as well as pasted it.

Enjoy!

-John

EDIT - DON'T USE THIS CODE, SCROLL DOWN AND USE THE SHORTENED VERSION.

#cs

_ReduceMemory UDF
by John Taylor (jftuga)
Jul-9-2005

This function, _ReduceMemory(), can reduce the amount of memory that an AutoIt compiled .exe uses by ~50%
Essentially written by several other UDFs coded by w0uter :-)

Usage: call _ReduceMemory() from your script.  If it is a GUI app, call it just before entering the event loop

See also:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/emptyworkingset.asp

#ce


Global Const $PROCESS_ALL_ACCESS = 0x1f0fff

; from w0uter
; http://www.autoitscript.com/forum/index.php?showtopic=12651
Func _MemOpen($i_dwDesiredAccess, $i_bInheritHandle, $i_dwProcessId)
    Dim $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', $i_dwDesiredAccess, 'int', $i_bInheritHandle, 'int', $i_dwProcessId)
    If @error Then
        SetError(1)
        Return 0
    EndIf
    
    Return $ai_Handle[0]
EndFunc;==> _MemOpen()

; from w0uter
; http://www.autoitscript.com/forum/index.php?showtopic=13383
Func _GetPID()
    Dim $ai_GetCurrentProcessId = DllCall('kernel32.dll', 'int', 'GetCurrentProcessId')
    return $ai_GetCurrentProcessId[0]
EndFunc

; from w0uter
; http://www.autoitscript.com/forum/index.php?showtopic=13392
Func _ReduceMemory()
    Dim $Handle = _MemOpen($PROCESS_ALL_ACCESS, False, _GetPID())
    return DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $Handle)
EndFunc

ReduceMemory.au3

Edited by jftuga
Link to comment
Share on other sites

I like it, and to make w0uter a happy person, I took the liberty to git-r-don (I live about 30 minutes from Sanford, FL, home of Larry the Cable Guy :evil:)

Global Const $PROCESS_ALL_ACCESS = 0x1f0fff

Func _ReduceMemory()
    Dim $ai_GetCurrentProcessId = DllCall('kernel32.dll', 'int', 'GetCurrentProcessId')
    Dim $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', $PROCESS_ALL_ACCESS, 'int', False, 'int', $ai_GetCurrentProcessId[0])
    If @error Then
        SetError(1)
        Return 0
    EndIf
    return DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle)
EndFunc

That should work...I'll go and test it in a second... :)

Edit:

Is

return DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle)

supposed to return a blank string?

Edited by MSLx Fanboy

Writing AutoIt scripts since

_DateAdd("d", -2, _NowCalcDate())
Link to comment
Share on other sites

I like it, and to make w0uter a happy person, I took the liberty to git-r-don (I live about 30 minutes from Sanford, FL, home of Larry the Cable Guy :))

Many Blue Collar TV episodes are filmed here in Athens GA, although I have not been able to go to a taping, which are free.

-John

Edited by jftuga
Link to comment
Share on other sites

Looks like a cool UDF. I will try it when I get back home from visting family in vermont as I only have my windows 98 laptop and it has no way of seeing memory usage in Task Manager (actually it does not evan have task manager.)

Will have to try it on my XP computer.

Edited by SolidSnake
HKTunes:Softpedia | GoogleCodeLyricToy:Softpedia | GoogleCodeRCTunes:Softpedia | GoogleCodeMichtaToolsProgrammer n. - An ingenious device that turns caffeine into code.
Link to comment
Share on other sites

return DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle)

should become

Local $ai_return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
return $ai_return[0]

also use local instead of Dim.

total would be like:

Func _ReduceMemory()
    Local $ai_GetCurrentProcessId = DllCall('kernel32.dll', 'int', 'GetCurrentProcessId')
    Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $ai_GetCurrentProcessId[0])
    Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
    Return $ai_Return[0]
EndFunc
Edited by w0uter

My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll

Link to comment
Share on other sites

forgot to close the handle:

Func _ReduceMemory()
    Local $ai_GetCurrentProcessId = DllCall('kernel32.dll', 'int', 'GetCurrentProcessId')
    Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $ai_GetCurrentProcessId[0])
    Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
    DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
    Return $ai_Return[0]
EndFunc

My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll

Link to comment
Share on other sites

Oh Snap!  Ran the code again, and Task Manager reported a drop from 3404 to 656, a near 520% decrease!!!

I love this thing!

<{POST_SNAPBACK}>

I'm no math scholar... but isn't 520% of 3404 equal to 17700.8?

And as such, a 520% drop from 3404 would be -14296.8, would it not?

3404 to 656 is about an 81% drop. I believe you did your math backwards (divided 3404 by 656, when to get the percentage of drop you find the difference of 3404 and 656 (2748) and then divide that by 3404, giving you ~0.807)...

But enough about that, I just thought it looked funny.

BACK ON TOPIC...

The function works great. I created a program with GUI that let's me create hotkeys for running programs and stuff (my own personal replacement for WinKey [i was going to find a link.. but it appears Copernic isn't providing it anymore, and Download.com doesn't have it either]). It was running with a hefty 4mb+ of memory, so I have it call _ReduceMemory() everytime the window is hidden/minimized and it drops it down to around 1800 (actually drops to about 1400, but it pops up to 1750-1800 right away). Awesome function, and one of the few non-personal UDFs that I'll keep on using.

Link to comment
Share on other sites

Hehe, I was never too good with percentages :)

<{POST_SNAPBACK}>

I tried _ReduceMemory too, works great, drops mem useage in half for me.

Ps, my engineers always messed up % change too, until I made them say ten times each day for a week "Percent change is new value minus old value over old value times 100%! :evil:

Regards

Larry

I'm, Lovin' IT, X

Link to comment
Share on other sites

Finally got around to trying it and it works great. :)

This should be added to the UDF libary that comes with AutoIt. You should post it here.

P.S. Does anybody know of a good resource on dlls\com objects besides MSDN.

-SolidSnake

HKTunes:Softpedia | GoogleCodeLyricToy:Softpedia | GoogleCodeRCTunes:Softpedia | GoogleCodeMichtaToolsProgrammer n. - An ingenious device that turns caffeine into code.
Link to comment
Share on other sites

It's interesting.

I have little optimizations idea:

There is 3 times DllCall('kernel32.dll',...

and it 3x internaly do DllOpen, DllCall, DllClose

so we can in the begining use DllOpen('kernel32.dll')

then 3x DllCall

and at end DllClose

I'm not sure with this on 100% just idea ...

And note: This function works only on WinXP and above.

Link to comment
Share on other sites

will do.

[edit]

tested it. and it was slower.

[/edit]

[edit2]

is MSDN wrong here => http://msdn.microsoft.com/library/default....yworkingset.asp

it says that i need "PROCESS_QUERY_INFORMATION and PROCESS_SET_INFORMATION"

but if i use them. it will say ACCESS DENIED. while PROCESS_ALL_ACCESS works.

[/edit2]

Edited by w0uter

My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll

Link to comment
Share on other sites

@wOuter

tested it. and it was slower.

Have you tried this?

Func _ReduceMemory()
    Local $dll = DllOpen("kernel32.dll")
    Local $ai_GetCurrentProcessId = DllCall($dll, 'int', 'GetCurrentProcessId')
    Local $ai_Handle = DllCall($dll, 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $ai_GetCurrentProcessId[0])
    Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
    DllCall($dll, 'int', 'CloseHandle', 'int', $ai_Handle[0])
    DllClose($dll)
    Return $ai_Return[0]
EndFunc
Link to comment
Share on other sites

yep. well i used another variable for the dll.

but evrything else is the same :)

but does anyone know why

"PROCESS_QUERY_INFORMATION and PROCESS_SET_INFORMATION"

dont work

My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll

Link to comment
Share on other sites

ok. did some digging. found "GetCurrentProcess".

wich is faster then getting the pid and opening itself.

noticed it always returned -1 so i just left that call out.

also made it affect other processes.

heres what i came up with.

[edit] forgot to close the handle *again* [/edit]

Func _ReduceMemory($i_PID = -1)
    
    If $i_PID <> -1 Then
        Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID)
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
        DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
    Else
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
    EndIf
    
    Return $ai_Return[0]
EndFunc;==> _ReduceMemory()

some results:

Word XP

14.076 KB -> 624 KB

3dsmax 7

142.356 KB -> 2.184 KB

Notepad

4.796 KB -> 112 KB

Edited by w0uter

My UDF's:;mem stuff_Mem;ftp stuff_FTP ( OLD );inet stuff_INetGetSource ( OLD )_INetGetImage _INetBrowse ( Collection )_EncodeUrl_NetStat_Google;random stuff_iPixelSearch_DiceRoll

Link to comment
Share on other sites

ok. did some digging. found "GetCurrentProcess".

wich is faster then getting the pid and opening itself.

noticed it always returned -1 so i just left that call out.

also made it affect other processes.

heres what i came up with.

[edit] forgot to close the handle *again* [/edit]

Func _ReduceMemory($i_PID = -1)
    
    If $i_PID <> -1 Then
        Local $ai_Handle = DllCall("kernel32.dll", 'int', 'OpenProcess', 'int', 0x1f0fff, 'int', False, 'int', $i_PID)
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', $ai_Handle[0])
        DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $ai_Handle[0])
    Else
        Local $ai_Return = DllCall("psapi.dll", 'int', 'EmptyWorkingSet', 'long', -1)
    EndIf
    
    Return $ai_Return[0]
EndFunc;==> _ReduceMemory()

some results:

Word XP

14.076 KB -> 624 KB

3dsmax 7

142.356 KB -> 2.184 KB

Notepad

4.796 KB -> 112 KB

<{POST_SNAPBACK}>

Great result with 3dsmax. :)

Nice UDF. :evil:

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...