Jump to content
Sign in to follow this  
psynegy

Optimisation

Recommended Posts

psynegy

Any ideas on how I could optimise this code? In a loop it seems to add quite a bit of a lag... :\

Func msnwindowlist()
    $processes = ProcessList("msnmsgr.exe")
    For $i = 1 To $processes[0][0]
        $MSNPID = $processes[$i][1]
    Next
    $var = WinList()
    $list = ""
    For $i = 1 to $var[0][0]
        If WinGetProcess($var[$i][0]) = $MSNPID AND $var[$i][0] <> "Windows Live Messenger" AND $var[$i][0] <> "" AND IsVisible($var[$i][1]) AND StringRight($var[$i][0], 5) <> "Alert" Then
            $list = $list & $var[$i][0] & @LF
        EndIf
    Next
    
    If $list = "" Then
        Return 0
    Else
        Return $list
    EndIf
EndFunc

Share this post


Link to post
Share on other sites
AgentSmith15

Func msnwindowlist()
    $processes = ProcessList("msnmsgr.exe")
    For $i = 1 To $processes[0][0]
        $MSNPID = $processes[$i][1]
    Next
    $var = WinList()
    $list = ""
    For $i = 1 to $var[0][0]
        If WinGetProcess($var[$i][0]) = $MSNPID AND $var[$i][0] <> "Windows Live Messenger" AND $var[$i][0] <> "" AND IsVisible($var[$i][1]) AND StringRight($var[$i][0], 5) <> "Alert" Then
            $list = $list & $var[$i][0] & @LF
        EndIf
    Next
    
    If $list = "" Then
        Return 0
    Else
                Sleep(10)
        Return $list
    EndIf
EndFunc

Does that do anything?

I see there isn't a pause so the function is constantly running. There shouldn't be any effect from adding a sleep..

Share this post


Link to post
Share on other sites
psynegy

Func msnwindowlist()
    $processes = ProcessList("msnmsgr.exe")
    For $i = 1 To $processes[0][0]
        $MSNPID = $processes[$i][1]
    Next
    $var = WinList()
    $list = ""
    For $i = 1 to $var[0][0]
        If WinGetProcess($var[$i][0]) = $MSNPID AND $var[$i][0] <> "Windows Live Messenger" AND $var[$i][0] <> "" AND IsVisible($var[$i][1]) AND StringRight($var[$i][0], 5) <> "Alert" Then
            $list = $list & $var[$i][0] & @LF
        EndIf
    Next
    
    If $list = "" Then
        Return 0
    Else
                Sleep(10)
        Return $list
    EndIf
EndFunc

Does that do anything?

I see there isn't a pause so the function is constantly running. There shouldn't be any effect from adding a sleep..

I have done a small fix, I now only run the check after there has been no user input after 1 second, which means the GUI doesn't get bogged down with the script running. I might put the Sleep in too though, so it doesn't eat up CPU.

Cheers :)

Share this post


Link to post
Share on other sites
TurionAltec

ProcessSetPriority ( @AutoitPID, 1)

Will set the priority of the script below normal, so it won't steal cpu time from other applications.

Is this function being called inside a tight loop in the main function? If so, add a sleep in there. Something like 250ms may be enough.

Unless there's reason to believe multiple msnmsgr.exe are running, why not just do ProcessExists("msnmsgr.exe") to get the PID for MSN. Get the value once before the loop, then refer to it by variable

Are you looking for Live messenger chat windows?

In version 8, they have in the title "Conversation", and the class "IMWindowClass". This might let you reduce the number of windows you have to process, and also fewer logic checks on the window, which should allow the function to finish faster. In the script below I changed the option for title matching, you may be able to bypass that and just do WinList("[CLASS:IMWindowClass]")

For WinGetProcess(), refer to it by window handle ($var[$i][1]) instead of title, which might make it quicker

Here's some code with these improvements

Global $MSNPID=ProcessExists("msnmsgr.exe")
Opt("WinTitleMatchMode",2) ;Search substrings of window titles
ProcessSetPriority ( @AutoitPID, 1) ;Lower script priority
While 1
    $list=msnwindowlist()
    ;Code that cares about the list
    sleep(250) ;delay only makes msnwindowlist run 4 times a second, which is probably responsive enough
WEnd
;End main code area

Func msnwindowlist()
    $var = WinList("[TITLE:Conversation; CLASS:IMWindowClass]")
    $list = ""
    For $i = 1 to $var[0][0]
        If WinGetProcess($var[$i][1]) = $MSNPID AND IsVisible($var[$i][1]) Then
            $list = $list & $var[$i][0] & @LF
        EndIf
    Next
    
    If $list = "" Then
        Return 0
    Else
        Return $list
    EndIf
EndFunc
Edited by TurionAltec

Share this post


Link to post
Share on other sites
TurionAltec

I did some tests. If you can just match the class, it's by far the fastest. Plus it returns almost 1/100th the results that you get listing all windows, which will drastically speed up the rest of the function.

I also process a loop of Wingetprocess, one with the handle, one with the title. As you can see it is drastically faster with the handle rather than title, and processing 4 entries is a lot quicker than 395

$timer=TimerInit()
$list=WinList("[CLASS:IMWindowClass]")
$timer=TimerDiff($timer)
ConsoleWrite("Using class: "&$timer &@CRLF)
ConsoleWrite("matches: "&$list[0][0]&@CRLF)
$timer=TimerInit()
$list=WinList()
$timer=TimerDiff($timer)
ConsoleWrite("Listing all: "&$timer &@CRLF)
ConsoleWrite("matches: "&$list[0][0]&@CRLF)
$timer=TimerInit()
For $i = 1 to $list[0][0]
    WinGetProcess($list[$i][1])
Next
$timer=TimerDiff($timer)
ConsoleWrite("hwnd process: "&$timer&@CRLF)
$timer=TimerInit()
For $i = 1 to $list[0][0]
    WinGetProcess($list[$i][0])
Next
$timer=TimerDiff($timer)
ConsoleWrite("title process: "&$timer&@CRLF)
Opt("WinTitleMatchMode",2)
$timer=TimerInit()
$list=WinList("Conversation")
$timer=TimerDiff($timer)
ConsoleWrite("Using title: "&$timer &@CRLF)
ConsoleWrite("matches: "&$list[0][0]&@CRLF)
$timer=TimerInit()
For $i = 1 to $list[0][0]
    WinGetProcess($list[$i][1])
Next
$timer=TimerDiff($timer)
ConsoleWrite("hwnd process: "&$timer&@CRLF)
$timer=TimerInit()
For $i = 1 to $list[0][0]
    WinGetProcess($list[$i][0])
Next
$timer=TimerDiff($timer)
ConsoleWrite("title process: "&$timer&@CRLF)

Results:

Using class: 0.840609630553604
matches: 4
Listing all: 5.70016580319566
matches: 395
hwnd process: 6.38125795317561
title process: 91.5068814611913
Using title: 2.10278121940079
matches: 4
hwnd process: 0.0466539741782824
title process: 3.90384811477436

edit:Added Wingetprocess

EDIT: here's some testing of the whole code:

CODE
$timer=TimerInit()

For $j =1 to 10

$list=msnwindowlist()

Next

$timer=TimerDiff($timer)/10

ConsoleWrite("Orig function avg loop time "&$timer&@CRLF)

ConsoleWrite($list&@CRLF)

Global $MSNPID=ProcessExists("msnmsgr.exe")

$timer=TimerInit()

For $j =1 to 10

$list=msnwindowlist1()

Next

$timer=TimerDiff($timer)/10

ConsoleWrite("New function avg loop time "&$timer&@CRLF)

ConsoleWrite($list&@CRLF)

;End main function

Func msnwindowlist()

$processes = ProcessList("msnmsgr.exe")

For $i = 1 To $processes[0][0]

$MSNPID = $processes[$i][1]

Next

$var = WinList()

$list = ""

For $i = 1 to $var[0][0]

If WinGetProcess($var[$i][0]) = $MSNPID AND $var[$i][0] <> "Windows Live Messenger" AND $var[$i][0] <> "" AND IsVisible($var[$i][1]) AND StringRight($var[$i][0], 5) <> "Alert" Then

$list = $list & $var[$i][0] & @LF

EndIf

Next

If $list = "" Then

Return 0

Else

Return $list

EndIf

EndFunc

Func IsVisible($handle)

If BitAnd( WinGetState($handle), 2 ) Then

Return 1

Else

Return 0

EndIf

EndFunc

Func msnwindowlist1()

$var = WinList("[CLASS:IMWindowClass]")

$list = ""

For $i = 1 to $var[0][0]

If WinGetProcess($var[$i][1]) = $MSNPID AND IsVisible($var[$i][1]) Then

$list = $list & $var[$i][0] & @LF

EndIf

Next

If $list = "" Then

Return 0

Else

Return $list

EndIf

EndFunc

Orig function avg loop time 105.975982981077
Rick - Conversation
Jeff - Conversation
John - Conversation
Andrew - Conversation

New function avg loop time 2.91564989405078
Rick - Conversation
Jeff - Conversation
John - Conversation
Andrew - Conversation
Edited by TurionAltec

Share this post


Link to post
Share on other sites
Valuater

The only problem with the above code having a large sleep is you need to use "OnEventMode" because GUIGetMsg() will not work well at all.

another approach... Adlib()

Opt("WinTitleMatchMode",2) ;Search substrings of window titles

Global $MSNPID=ProcessExists("msnmsgr.exe")

ProcessSetPriority ( @AutoitPID, 1) ;Lower script priority
AdlibEnable("msnwindowlist", 500) ; this will handle the checking

While 1
    ;Code that cares about the list
WEnd

Func msnwindowlist()
    Local $list = "", $var = WinList("[TITLE:Conversation; CLASS:IMWindowClass]")
    For $i = 1 to $var[0][0]
        If WinGetProcess($var[$i][1]) = $MSNPID AND IsVisible($var[$i][1]) Then
            $list = $list & $var[$i][0] & @LF
        EndIf
    Next
    If $list = "" Then Return 0
    Return $list
EndFunc

8)


NEWHeader1.png

Share this post


Link to post
Share on other sites
Valuater

I see all of your edits and additions Turion, I just hope the OP does

8)


NEWHeader1.png

Share this post


Link to post
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
Sign in to follow this  

×