Jump to content

Infinite loops. Is this just me?


Recommended Posts

Often when I look over others scripts while trying to help people on the forums, I see something like

While True
    Sleep(1000) ; This is so the cpu usage doesn't go nuts.
WEnd

Valid point because I too noticed a while back that it hits 40% cpu usage if I don't slow down the loop at all.

But I also know that even lower end modern processors process about 15-150 billion Instructions per second.

Now I know many many instructions are used for each operation from a high level language standpoint but that is still a lot. It would seem to me that you could get just as good of results by only sleeping for 1 millisecond as you could for 1 second, because a millisecond from a processor standpoint allows a ton of instructions through.

Basically it would be better to use this because it would not kill the cpu and still not slow down the rest of your program by any noticeable amount.

While True
    Sleep(1) ; This is so the cpu usage doesn't go nuts.
WEnd

Seems to work in simple testing for me. Can anyone disprove it?

-Shawn

Link to comment
Share on other sites

Seems to work in simple testing for me. Can anyone disprove it?

Probably not.

PS: The sleep command uses a general step value of about 10..12. So the effect of a sleep(1) or sleep(10) are effectively the same.

"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Link to comment
Share on other sites

A loop like that should only be used when waiting for an event message (correct me if I'm wrong). Event messages are processed in the middle of the sleep rather than waiting till the sleep ends.

This displays it nicely:

Opt("GUIOnEventMode",1)

HotKeySet("e","_HotKey") ;(press e)
GUICreate("OnEvent Test")
GUISetOnEvent(-3,"_GUISetOnEvent") ;(close GUI)
GUICtrlCreateButton("Event!",10,10)
GUICtrlSetOnEvent(-1,"_GUICtrlSetOnEvent") ;(press button)
GUISetState()
GUIRegisterMsg("0x0047","_GUIRegisterMsg") ;(Move GUI)

While 1
    Sleep(24*60*60*1000) ;sleep one day to REALY reduce cpu usage
    ConsoleWrite("Sleep complete!" & @CRLF) ;this should not print unless you leave it running.
WEnd

Func _HotKey()
    MsgBox(0,"Event!","E was pressed!")
EndFunc

Func _GUISetOnEvent()
    MsgBox(0,"Event!","The GUI is closed!")
    Exit
EndFunc

Func _GUICtrlSetOnEvent()
    MsgBox(0,"Event!","Event button was pressed!")
EndFunc

Func _GUIRegisterMsg()
    MsgBox(0,"Event!","The GUI was moved!")
EndFunc

GuiGetMsg automatically idles the cpu, so it should not be combined with a sleep().

If a loop has a way to exit, or if a loop contains function calls the sleep should be appropriately short so that the user doesn't experience a noticable delay as you posted.

Link to comment
Share on other sites

Event messages are processed in the middle of the sleep rather than waiting till the sleep ends.

Technically probably incorrect, but events (OnEvent, Hotkeys, Adlib, etc) don't wait for anything. They spawn a new code processing line while putting the current code processing line on hold. No matter what command is/was currently being processed (sleep or otherwise.)(ignoring exceptions to the rule.)

Ps: Your code only shows(proofs) that in relation to sleep, sleep will no block other event calls.

Edited by MvGulik

"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Link to comment
Share on other sites

Technically probably incorrect, but events (OnEvent, Hotkeys, Adlib, etc) don't wait for anything. They spawn a new code processing line while putting the current code processing line on hold. No matter what command is/was currently being processed (sleep or otherwise.)(ignoring exceptions to the rule.)

Ps: Your code only shows(proofs) that in relation to sleep, sleep will no block other event calls.

Would you believe me if I tell you you got it all wrong?

You are fooled by the way Sleep() is implemented in AutoIt.

While sleep everything sleeps for real. But Sleep() is in reality series of linked sleeps. Functions you mention are executed in the mean time, i.e. they wait all right.

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

I wasn't making assumtions about the way it's implemented. (didn't mean to anyways), but rather tried to best explain the way AutoIt behaves for the end user.

For that purpose I think my explanation was correct, or am I missing something here?

Link to comment
Share on other sites

I wasn't making assumtions about the way it's implemented. (didn't mean to anyways), but rather tried to best explain the way AutoIt behaves for the end user.

I know.

Its more or less the same for me btw. "Technically probably incorrect" -> or: mainly from a AutoIt user's code point of view.

With

Event messages are processed in the middle of the sleep rather than waiting till the sleep ends.

I feel your kinda suggesting there is some relation between sleep() and event driven code execution. And from a users code point of view there is no relation. (At least not to me. Might change today ... maybe.)

"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Link to comment
Share on other sites

Would you believe me if I tell you you got it all wrong?

That I'm wrong. Sure.

That your right ... Depends on if I'm able to follow any additional supplied argumentation and if it can match it up with there intended contextual point of view.

You are fooled by the way Sleep() is implemented in AutoIt.

Not really sure I'm following you here.

- I have never seen how sleep is implemented in AutoIt itself.

- You mean: "... fooled by the virtual way sleep seems to work from a AutoIt users point of view, compared to how sleep actually is implemented in AutoIt itself" ?

The "Technically probably incorrect" was my way of saying something similar. That part seems to have backfired.

While sleep everything sleeps for real. But Sleep() is in reality series of linked sleeps.

That crossed my mind, and made sense. But I did not see the significants of this to the virtual way AutoIt code is executed or behaves.

Functions you mention are executed in the mean time, i.e. they wait all right.

You lost me here.

- Assuming internal AutoIt POV.

- What do you mean with "in the mean time".

- "They wait all right". wait for what? Internal/real issued sleep commands by AutoIt? (That makes no sens to me. As AutoIt can be considered out-cold when "its" in a true sleeping state. With 'Waiting' I presume some sort of active state.)

"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Link to comment
Share on other sites

Not really sure I'm following you here.

- I have never seen how sleep is implemented in AutoIt itself.

- You mean: "... fooled by the virtual way sleep seems to work from a AutoIt users point of view, compared to how sleep actually is implemented in AutoIt itself" ?

The "Technically probably incorrect" was my way of saying something similar. That part seems to have backfired.

You have wrong assumptions and derived wrong conclusions. All based on wrong premises (if any).

That crossed my mind, and made sense. But I did not see the significants of this to the virtual way AutoIt code is executed or behaves.

AutoIt is high level language in development phase. Serious work with it requires understanding of the internal workings. Anyone (and I mean anyone) saying different is plain ignorant.

You lost me here.

- Assuming internal AutoIt POV.

- What do you mean with "in the mean time".

- "They wait all right". wait for what? Internal/real issued sleep commands by AutoIt? (That makes no sens to me. As AutoIt can be considered out-cold when "its" in a true sleeping state. With 'Waiting' I presume some sort of active state.)

When you do Sleep(250) AutoIt will (most likely) split that to 25 calls to Sleep function -the one I linked to. Between those sleeps AutoIt will be active. Proving this is trivial but since the audience isn't of that type, I won't for example.

And functions that use other threads (Inet... whatever) shouldn't be affected by any sleep.

Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

Right. I'm cutting this "trancexx versus me" short as I don't see this resulting in anything useful.

Anyone that thinks he/she (or both) can clear up the confusion. ... (Here or PM if you like).

Edited by MvGulik

"Straight_and_Crooked_Thinking" : A "classic guide to ferreting out untruths, half-truths, and other distortions of facts in political and social discussions."
"The Secrets of Quantum Physics" : New and excellent 2 part documentary on Quantum Physics by Jim Al-Khalili. (Dec 2014)

"Believing what you know ain't so" ...

Knock Knock ...
 

Link to comment
Share on other sites

I can't necessarily say how AutoIt currently does it, but we do know how it USED to handle sleeps based on the old source code.

First, the function itself:

AUT_RESULT AutoIt_Script::F_Sleep(VectorVariant &vParams, Variant &vResult)
{
    // Handle sleep 0 as a special
    if (vParams[0].nValue() <= 0)
        ::Sleep(0);
    else
    {
        m_tWinTimerStarted  = timeGetTime();    // Using the WinWait timer - go fig.
        m_nWinWaitTimeout   = vParams[0].nValue();
        m_nCurrentOperation = AUT_SLEEP;
        Execute();
    }

    return AUT_OK;

} // Sleep()

So from here we see that Sleep(0) actually directly invokes the windows API Sleep(). Otherwise it leverages a custom timing mechanic (in fact, the same one used for WinWait) and invokes a separate call to Execute() (which is the line-by-line function handler). Following the Execute() code we see:

AUT_RESULT AutoIt_Script::Execute(int nScriptLine)
{
    MSG         msg;
    VectorToken LineTokens;                     // Vector (array) of tokens for a line of script
    const char  *szScriptLine;
        ...
        ...
        while(m_bWinQuitProcessed == false && m_bUserFuncReturned == false)
    {
        // Run the windows message loop and handle quit conditions
        ProcessMessages();

        // If script is in a quit state then don't execute any more code
        if (m_nCurrentOperation == AUT_QUIT)
            break;                              // Exit while loop

        // If we are waiting for something (winwait, sleep, paused, etc) then loop again
        if (HandleDelayedFunctions() == true)
            continue;
       ...
       ....
}

The "HandleDelayedFunctions" function is where it does the actual 'sleeping', the execute loop just calls that until it returns false:

HandleDelayedFunctions does what its name implies, and handles the various waiting functions in AutoIt, among them all of the "proccess waits", handled by this function (only the first part is included, since it pertains to the discussion):

bool AutoIt_Script::HandleProcessWait(void)
{
    // Any ProcessWait commands to process?
    if (m_nCurrentOperation != AUT_PROCESSWAIT && m_nCurrentOperation != AUT_PROCESSWAITCLOSE)
        return false;

    // Idle a little to remove CPU usage
    Sleep(AUT_IDLE);


    // If required, process the timeout
    if (m_nProcessWaitTimeout != 0)
    {
        // Get current time in ms
        DWORD   dwDiff;
        DWORD   dwCur = timeGetTime();
        if (dwCur < m_tProcessTimerStarted)
            dwDiff = (UINT_MAX - m_tProcessTimerStarted) + dwCur; // timer wraps at 2^32
        else
            dwDiff = dwCur - m_tProcessTimerStarted;

        // Timer elapsed?
        if (dwDiff >= m_nProcessWaitTimeout)
        {
            m_vUserRetVal = 0;                  // We timed out (default = 1)
            m_bUserFuncReturned = true;         // Request exit from Execute()
            m_nCurrentOperation = AUT_RUN;      // Continue script
            return true;
        }
    }
       ...
       ...
}

So we see that it actually just does a poll to see how much time has elapsed since the timer init (standard wait behavior). Also, it directly invokes this line:

// Idle a little to remove CPU usage
Sleep(AUT_IDLE);

which is a constant of 10. Which tells us that even a Sleep(1) in AutoIt, calls a Sleep(10) to the Windows API already.

As to the OP's question:

I'd say that circumstantially, you'd either want to do a sleep(0), to give another processes some time share, sleep(1)-sleep(10) if you want to give the minimal "AutoIt aware" sleep value, or something higher, like Sleep(500) if you don't need the script to be instantaneously responsive.

Edited by evilertoaster
Link to comment
Share on other sites

If you really want to sleep for 1 ms (or even something much lower), then look at _HighPrecisionSleep()

Edited by AdmiralAlkex
Link to comment
Share on other sites

Thanks evilertoaster,

I was watching this thread go way off track, your the only one that kind of understood what I was talking about. All I was asking is that if your goal is only to reduce CPU load from an infinite loop with no delays, then is there any real benefit from the commonly used Sleep(1000) or Sleep(500) over Sleep(1)? And furthermore wouldn't Sleep(1) be better since it does less damage to the speed of the program?

In my tests, Sleep(0) still causes a cpu load (35-40%), whereas Sleep(1) does not (doesn't even register as a % usage). So I think Sleep(1) might be better if your goal is to have a fast infinite loop, with unnoticeable delay, and no abnormal cpu usage spikes.

-Shawn

Edited by ShawnW
Link to comment
Share on other sites

I think Sleep(1) might be better if your goal is to have a fast infinite loop, with unnoticeable delay, and no abnormal cpu usage spikes.

I still don't see the advantage of this over a longer sleep. Seen as looping Sleep(1) will repeatedly sleep for 10ms and Sleep(1000) will... repeatedly sleep for 10ms.

In OnEvent mode one should not be more responsive than the other. In messageloop mode there should not be a sleep.

The difference should only be notable if the loop also contains other code to be executed, which I don't hear you about.

Link to comment
Share on other sites

I still don't see the advantage of this over a longer sleep. Seen as looping Sleep(1) will repeatedly sleep for 10ms and Sleep(1000) will... repeatedly sleep for 10ms.

In OnEvent mode one should not be more responsive than the other. In messageloop mode there should not be a sleep.

The difference should only be notable if the loop also contains other code to be executed, which I don't hear you about.

Well not all scripts require user response or events. Say I want a script to loop in the background doing some task, or maybe constantly checking something, or even a series of mouse clicks. The point is there are times when you want quick program looping so you get continuous iterations, where there are no events because all it is doing is running more code over and over. Yet without sleep the cpu usage would skyrocket.

-Shawn

Link to comment
Share on other sites

@ShawnW

You seemed to have miss what eviltoaster really said.

Which tells us that even a Sleep(1) in AutoIt, calls a Sleep(10) to the Windows API already.

So Sleep(1) is completely pointless, and is only going to create confusion. Either use Sleep(10) or _HighPrecisionSleep(), which works down to 100 nano seconds.

Link to comment
Share on other sites

@ShawnW

You seemed to have miss what eviltoaster really said.

So Sleep(1) is completely pointless, and is only going to create confusion. Either use Sleep(10) or _HighPrecisionSleep(), which works down to 100 nano seconds.

I appreciate your concern, and _HighPrecisionSleep() certainly seems like a useful function to use in the future, but this is not what I'm trying to do.

I wasn't comparing 1 to 10, (although I'm not sure I buy that, not the point and I don't wish to discuss it) I was comparing it to something that might actually make a difference. I'll make the argument Sleep(10) better than Sleep(500) or Sleep(1000) if it makes you happy. The only thing I'm questioning is the minimum amount of delay required to keep the CPU load from going nuts.

Edited by ShawnW
Link to comment
Share on other sites

The only thing I'm questioning is the minimum amount of delay required to keep the CPU load from going nuts.

Did you see this note by monoceres in the thread I linked too? (post #9)

Actually, I just tested and 100 nanoseconds of sleep is enough to keep the CPU percentage at 0% on my machine

So the time you choose is pretty much irrelevant.

Edit: But I would think that bigger is better, unless you have a reason to go really low. If nothing else, at least I would expect that to be more energy efficient (laptops are popular nowadays).

Edited by AdmiralAlkex
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...