Sign in to follow this  
Followers 0
12321

High CPU usage while WinWaitNotActive

13 posts in this topic

Dear all,

I am new to AutoIt and I am confused why my script has such high CPU usage.

The script only checks the title of the active window and then waits until that window is not active anymore. Then it checks the title of the new active window and so on and so on....

I included Debug.au3. And it tells me that the script is atm at the WinWaitNotActive($wintitle) but it has a CPU usage of average of 5%.

#region options
Opt("MustDeclareVars", 1)
AutoItSetOption("TrayIconDebug", 1)
#endregion options

#region include
#include<File.au3>
#include<Array.au3>
#include<Debug.au3>
#include<Process.au3>
#include<WindowsConstants.au3>
#include<GUIConstantsEx.au3>
#include<EditConstants.au3>
_DebugSetup("debug", 1)
#endregion include

#region variables
Global $wintitle
#endregion variables

#region loop
While 1 ; ### loop ###
    _DebugOut("StartOfLoop")
    $wintitle = WinGetTitle("[ACTIVE]") ;title from active window
    If $wintitle Then ;check that $wintitle is not empty. Else sleep(250).
     _DebugOut("BeforeWinWaitActive")
        WinWaitNotActive($wintitle)
     _DebugOut("AfterWinWaitActive")
    Else
        Sleep(250)
    EndIf
    _DebugOut("EndOfLoop")
WEnd
#endregion loop

Share this post


Link to post
Share on other sites



Why do you wait for the window to become inactive in a loop? You just wait in the loop (no other statements) so you could replace the loop with a single WinWaitNotActive:

$wintitle = WinGetTitle("[ACTIVE]") ;title from active window
WinWaitNotActive($wintitle)

My UDFs and Tutorials:

Spoiler

UDFs:
Active Directory (NEW 2017-04-18 - Version 1.4.8.0) - Download - General Help & Support - Example Scripts - Wiki
OutlookEX (NEW 2017-02-27 - Version 1.3.1.0) - Download - General Help & Support - Example Scripts - Wiki
ExcelChart (2015-04-01 - Version 0.4.0.0) - Download - General Help & Support - Example Scripts
Excel - Example Scripts - Wiki
Word - Wiki
PowerPoint (2015-06-06 - Version 0.0.5.0) - Download - General Help & Support

Tutorials:
ADO - Wiki

 

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Well I just tried it with that test script and realized that I still had the same problem with the high CPU usage like in my "real" script.

My real script is longer, so I just posted the test script.

Below you can find my "real" script. To run this script 4 files are necessary:

listsWhitelistTitle

listsWhitelistProcess

listsBlacklistProcess

listsBlacklistTitle

But I observe the high CPU usage in both scripts.

#region options
Opt("MustDeclareVars", 1)
AutoItSetOption("TrayIconDebug", 1)
AutoItSetOption("TrayAutoPause", 0)
;~ AutoItSetOption("TrayIconHide",1)
#endregion options

#region include
#include<File.au3>
#include<Array.au3>
#include<Debug.au3>
#include<Process.au3>
#include<WindowsConstants.au3>
#include<GUIConstantsEx.au3>
#include<EditConstants.au3>
_DebugSetup("debug procrastination", 1)
#endregion include

#region variables
Global $aWhitelistTitle
Global $aWhitelistProcess
Global $aBlacklistProcess
Global $aBlacklistTitle
Global $hGUI
Global $input_process
Global $input_title
Global $button_whitelist_process
Global $button_whitelist_title
Global $button_blacklist_process
Global $button_blacklist_title
Global $GUImsg
Global $learn_new
#endregion variables

#region load lists
; whitelist_title to array
Global $sFile1 = @ScriptDir & "listsWhitelistTitle" ;WhitelistTitle file one entry per line
_FileReadToArray($sFile1, $aWhitelistTitle)
If @error = 1 Then
    MsgBox(4096, "Error", "Error opening file: WhitelistTitle")
    Exit
ElseIf @error = 2 Then
    MsgBox(4096, "Error", "Corrupted file: WhitelistTitle")
    Exit
EndIf
_DebugOut("Whitelist_title2Array_Successful")
Sleep(100)

; whitelist_title to array
Global $sFile2 = @ScriptDir & "listsWhitelistProcess" ;WhitelistProcess file one entry per line
_FileReadToArray($sFile2, $aWhitelistProcess)
If @error = 1 Then
    MsgBox(4096, "Error", "Error opening file: WhitelistProcess")
    Exit
ElseIf @error = 2 Then
    MsgBox(4096, "Error", "Corrupted file: WhitelistProcess")
    Exit
EndIf
_DebugOut("Whitelist_process2Array_Successful")
Sleep(100)

; blacklist process to array
Global $sFile3 = @ScriptDir & "listsBlacklistProcess" ;BlacklistProcess file one entry per line
_FileReadToArray($sFile3, $aBlacklistProcess)
If @error = 1 Then
    MsgBox(4096, "Error", "Error opening file: BlacklistProcess")
    Exit
ElseIf @error = 2 Then
    MsgBox(4096, "Error", "Corrupted file: BlacklistProcess")
    Exit
EndIf
_DebugOut("Blacklist_process2Array_Successful")

; blacklist title to array
Global $sFile4 = @ScriptDir & "listsBlacklistTitle" ;BlacklistTitle file one entry per line
_FileReadToArray($sFile4, $aBlacklistTitle)
If @error = 1 Then
    MsgBox(4096, "Error", "Error opening file: BlacklistTitle")
    Exit
ElseIf @error = 2 Then
    MsgBox(4096, "Error", "Corrupted file: BlacklistTitle")
    Exit
EndIf
_DebugOut("Blacklist_title2Array_Successful")
Sleep(100)
#endregion load lists





#region loop
$learn_new = 1 ; variable that checks if a process or title is already in the arrray
While 1 ; ### loop ###

    _DebugOut("StartOfLoop")
    Global $wintitle = WinGetTitle("[ACTIVE]") ;title from active window
    If $wintitle Then ;check that $wintitle is not empty. Else sleep(250).
        Global $winprocess = _ProcessGetName(WinGetProcess($wintitle)) ;process name from active window

        For $i = 1 To $aWhitelistProcess[0] ;checks if the process name is on the whitelist
            Sleep(50)
            If $winprocess = $aWhitelistProcess[$i] Then
                _DebugOut("Whitelist_process_BeforePause")
                WinWaitNotActive($wintitle) ;if process name is on whitelist script pauses until other window is active.
                _DebugOut("Whitelist_process_AfterPause")
                $learn_new = 0 ; if process name is on whitelist no need to learn new process name
            EndIf
        Next
        Sleep(50)

        If $learn_new Then ;only check other lists if process is not in whitelist_process (hence if the For loop haven't set the $learn_new variable to 0).
            For $i = 1 To $aBlacklistProcess[0] ;checks if the process name is on the blacklist
                If $winprocess = $aBlacklistProcess[$i] Then
                    ProcessClose($winprocess) ;close process if on blacklist
                    $learn_new = 0 ;if name on list no need to learn new process name
                    _DebugOut("processclose")
                EndIf
            Next
            Sleep(50)

            If $learn_new Then ;only check other lists if process is not in whitelistprocess AND blacklistprocess
                For $i = 1 To $aBlacklistTitle[0] ;checks if the window title is on the blacklist
                    If StringInStr($wintitle, $aBlacklistTitle[$i]) Then
                        WinSetState($wintitle, "", @SW_HIDE) ;hide window if on blacklist
                        $learn_new = 0 ;if name on list no need to learn new process name
                        _DebugOut("winclose")
                    EndIf
                Next
                Sleep(50)

                If $learn_new Then ;only check list if process is not in whitelistprocess AND blacklistprocess OR title is not in blacklist
                    For $i = 1 To $aWhitelistTitle[0] ;checks if the window title is on the whitelist
                        If StringInStr($wintitle, $aWhitelistTitle[$i]) Then
                            _DebugOut("Whitelist_title_BeforePause")
                            WinWaitNotActive($wintitle) ;if process name is on whitelist script pauses until other window is active.
                            _DebugOut("Whitelist_title_AfterPause")
                            $learn_new = 0 ;if name on list no need to learn new process name
                        EndIf
                    Next
                    Sleep(50)
                EndIf

            EndIf
        EndIf

        _learnnew()
        _learnnewgetmsg()
        Sleep(50)
        $learn_new = 1

    Else
        Sleep(250)
    EndIf

    _DebugOut("EndOfLoop")
WEnd
#endregion loop



#region functions
Func _learnnew() ;create GUI if new programm
    If $learn_new Then
        $hGUI = GUICreate("Learning mode - Procrastination Killer", 425, 85, -1, -1, -1, $WS_EX_TOPMOST)
        $input_process = GUICtrlCreateInput($winprocess, 5, 5, 415, 20, BitOR($ES_CENTER, $ES_READONLY))
        $input_title = GUICtrlCreateInput($wintitle, 5, 30, 415, 20, $ES_CENTER)
        $button_whitelist_process = GUICtrlCreateButton("Whitelist Process", 5, 55, 100, 25)
        $button_whitelist_title = GUICtrlCreateButton("Whitelist Title", 110, 55, 100, 25)
        $button_blacklist_process = GUICtrlCreateButton("Blacklist Process", 215, 55, 100, 25)
        $button_blacklist_title = GUICtrlCreateButton("Blacklist Title", 320, 55, 100, 25)
        GUISetState(@SW_SHOW)
    EndIf
EndFunc   ;==>_learnnew

Func _learnnewgetmsg() ;while GUI active GUIGetMsg
    While WinGetHandle("[ACTIVE]") = $hGUI
        $GUImsg = GUIGetMsg()
        Select
            Case $GUImsg = $button_whitelist_title
                _ArrayAdd($aWhitelistTitle, GUICtrlRead($input_title))
                _DebugOut("#whitelisttitle " & $aWhitelistTitle[0])
                $aWhitelistTitle[0] += 1
                _DebugOut("#whitelisttitle " & $aWhitelistTitle[0])
                Global $hFile1 = FileOpen($sFile1, 2)
                _FileWriteFromArray($hFile1, $aWhitelistTitle, 1)
                FileClose($hFile1)
                GUIDelete($hGUI)
            Case $GUImsg = $button_whitelist_process
                _ArrayAdd($aWhitelistProcess, GUICtrlRead($input_process))
                _DebugOut("#whitelistprocess " & $aWhitelistProcess[0])
                $aWhitelistProcess[0] += 1
                _DebugOut("#whitelistprocess " & $aWhitelistProcess[0])
                Global $hFile2 = FileOpen($sFile2, 2)
                _FileWriteFromArray($hFile2, $aWhitelistProcess, 1)
                FileClose($hFile2)
                GUIDelete($hGUI)
            Case $GUImsg = $button_blacklist_process
                _ArrayAdd($aBlacklistProcess, GUICtrlRead($input_process))
                _DebugOut("#blacklistprocess " & $aBlacklistProcess[0])
                $aBlacklistProcess[0] += 1
                _DebugOut("#blacklistprocess " & $aBlacklistProcess[0])
                Global $hFile3 = FileOpen($sFile3, 2)
                _FileWriteFromArray($hFile3, $aBlacklistProcess, 1)
                FileClose($hFile3)
                GUIDelete($hGUI)
            Case $GUImsg = $button_blacklist_title
                _ArrayAdd($aBlacklistTitle, GUICtrlRead($input_title))
                _DebugOut("#blacklisttitle " & $aBlacklistTitle[0])
                $aBlacklistTitle[0] += 1
                _DebugOut("#blacklisttitle " & $aBlacklistTitle[0])
                Global $hFile4 = FileOpen($sFile4, 2)
                _FileWriteFromArray($hFile4, $aBlacklistTitle, 1)
                FileClose($hFile4)
                GUIDelete($hGUI)
        EndSelect
    WEnd
EndFunc   ;==>_learnnewgetmsg
#endregion functions
Edited by 12321

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

I don't know if this will help or not but it is a different method.

Global $sWindowActive = False
Global $sWindow = "Window Title" ; or Handle
AdlibRegister("_IsWindowActive", 1000) ; Second parameter is interval in miliseconds to execute function.
; Your Main Loop
If $sWindowActive Then
   ; Do something here
   $sWindowActive = False ; Set global variable back to false.
EndIf
While 1
   Sleep(5000) ; This will not interupt the execution of the registered function.
WEnd

Func _IsWindowActive()
   If WinActive($sWindow) Then $sWindowActive = True
EndIf
Edited by Decipher

Spoiler

censored.jpg

 

Share this post


Link to post
Share on other sites

Wow! I just came back home and turn on my computer again. I was about to check the solution of Decipher. But first I ran the test script and my average CPU usage was slightly above zero when the script was at WinWaitNotActive. Then I tried the "real" script and the same result slightly above zero !!!

I have no clue what caused the high CPU usage of the both scripts, but without any change it's fine now!

btw I ran another script when I observed the high CPU usage and that didn't cause a high CPU usage...

Weired...

but thanks for the replys and AdlibRegister I might use for the GUIGetMsg() while the loop is running.

Share this post


Link to post
Share on other sites

Okay I was to quick with my reply.

Today I was working on that script again and I observed a rather high CPU usage again.

Maybe someone else can test it too?

Here two basic scripts to compare. Using the first one I have continuously a CPU usage of ~5%. But using the second one I have a CPU usage of ~0%.

While 1
   Local $wintitle = WinGetTitle("[ACTIVE]") ;title from active window
      If $wintitle Then ;check that $wintitle is not empty. Else sleep(250).
         WinWaitNotActive($wintitle)
      Else
         Sleep(250)
      EndIf
WEnd

While 1
   Local $wintitle = WinGetTitle("[ACTIVE]") ;title from active window
      If $wintitle Then ;check that $wintitle is not empty. Else sleep(250).
         Sleep(250)
      Else
         Sleep(250)
      EndIf
WEnd

Why this difference? I don't know.

Well I use in my script now Sleep(250) instead of WinWaitNotActive($wintitle)...

Share this post


Link to post
Share on other sites

12321,

Why this difference? I don't know

Why are you surprised at the difference? In the first snippet you are never giving the CPU a chance to take a breather if there is an active window (which there probably will be):

Start the loop:
   WinGetTitle
   If we have a title Then
      Run round the loop again with no pause
   Else
      Give the CPU a rest
   EndIf

See what I mean? ;)

In your second snippet you Sleep regardless of the condition - so you might as well put it outside the If structure and pause on every pass. :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Why are you surprised at the difference? In the first snippet you are never giving the CPU a chance to take a breather if there is an active window

...

See what I mean? ;)

Actually I do not see what you mean :huh:

The AutoIt help tells me "The script polls for a window match every 250 milliseconds or so."

So I thought that the CPU has 250ms time to take a breather. Did I misunderstood it?

BTW yes I know that the second script is nonsense... Just changed one line, was enough to test the CPU usage :rolleyes:

Edited by 12321

Share this post


Link to post
Share on other sites

12321,

You are quite right - my apologies. I completely misread the script. :>

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

I am new to AutoIt and programming and so on so I don't know :idiot:

But isn't the fact that WinWaitNotActive is not "sleeping" 250ms like described in the help file enough for a bug report?

BTW someone compared the high CPU usage of the 2 scripts on their computer (see ) ???

Share this post


Link to post
Share on other sites

It might be a problem with WinWaitNotActive, but here is a way to work around it; assuming that you to manually put in the sleep(250) to avoid high CPU usage, you could do something like

Local $wintitle
While 1
   $wintitle = WinGetTitle("[ACTIVE]")
   If $wintitle Then
      Do
         Sleep(250)
      Until Not WinActive($wintitle)
   EndIf
   Sleep(250)
WEnd

Share this post


Link to post
Share on other sites

12321,

I do not see the same high CPU usage as you when I run that script - it sits around 0-2% when nothing else is running which is about the norm for AutoIt. But if you want to open a bug report, please do so here. :)

M23


Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind._______My UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Share this post


Link to post
Share on other sites

@Melba23 Okay that's weird that you don't see the high CPU usage.

@lark thanks for the idea.

All three options should have more or less the same outcome and all "sleep" 250ms, but letting them run I find following CPU usages:

1. Using sleep(250) I have a max CPU usage of 1% and an average of ~0%.

2. Using WinWaitNotActive($wintitle) a max CPU usage of 10% and an average of ~5%.

3. Until Not WinActive($wintitle) has a max CPU usage of 2% and an average of ~0.1%

Over and over again same result. Well I cannot explain it, but as long as I found a nice solution [just a simple sleep(250)] it is okay :idiot:

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  
Followers 0