Tip: Reducing CPU usage in tight loops

Share your advanced PureBasic knowledge/code with the community.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by PB.

Don't know if this affects Amiga/Linux, but it does in Windows...

If you're using tight loops in Windows without the WaitWindowEvent() command,
the CPU can get used quite heavily. Take the following example: When running,
and when I check the Windows Task Manager, it shows that the loop is using a
massive 90% of my CPU's power:

Code: Select all

Repeat : r=r+1 : Until r=99999999
So, to prevent such high CPU use and keep your apps CPU-friendly, you should
always put in a Sleep_(1) command in the loop, to release the CPU load during
the loop. This next example shows this, and reduces the loop's CPU usage to a
much more desirable 0% when running, without having too much of an impact on
the loop's speed. But note: If you're coding an app for fast speed, then you
should perhaps not use this tip as it slows down the loop by 1 millisecond each
time the loop runs. Thus, it may not be good for games, but for desktop apps,
it should be used in all tight loops, and especially those which don't call the
WaitWindowEvent() command at all.

Code: Select all

Repeat : Sleep_(1) : r=r+1 : Until r=99999999

PB - Registered PureBasic Coder

Edited by - PB on 24 April 2002 04:42:02
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by tranquil.

Code: Select all

Repeat : Sleep_(1) : r=r+1 : Until r=99999999
Waiting for events in a Repeat:Sleep_():until loop is not the right way for doing that. You have REALY to wait e.g. with the waitmessage_() API Command for Window or other Application events. That provides you app with the Full-CPU Power (If needed) or with less then 1% if not.

Works very fine in my Sources.

Mike


Tranquilizer/ Secretly!
Registred PureBasic User
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by PB.
Waiting for events in a Repeat:Sleep_():until loop is not the right way for doing that. You have REALY to wait e.g. with the waitmessage_() API Command for Window or other Application events. That provides you app with the Full-CPU Power (If needed) or with less then 1% if not.
I'm talking about loops that *don't* wait for an event, as I said in my original
post. For example, often I code apps (for my own use) that use Repeat/Forever
because they constantly monitor something, and using Sleep_(1) is the only way
to reduce the CPU load during the loop because I'm not waiting for a Windows
event of any kind during this time.


PB - Registered PureBasic Coder

Edited by - PB on 24 April 2002 06:11:12
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by tranquil.

Yep, and thats right what you say PB. A sleep_(1) is a sulution, but not the best way. And that was the only think I wanted to mentioned here and tried to show an alternative to it for users how didn't know waitmessage_()

Cheers
Mike

Tranquilizer/ Secretly!
Registred PureBasic User
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by tinman.
Don't know if this affects Amiga/Linux, but it does in Windows...
If you want to do the same thing under AmigaOS you can use Delay_(x) where x is the number of 50ths of a second to put your program to sleep for.
the CPU can get used quite heavily. Take the following example: When running,
and when I check the Windows Task Manager, it shows that the loop is using a
massive 90% of my CPU's power:
Of course it would use a lot of CPU, the loop will run all the time :)


--
It's not minimalist - I'm increasing efficiency by reducing input effort.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by PB.

> tried to show an alternative to it for users how didn't know waitmessage_()

To be honest, I haven't used the WaitMessage API and would like to see an
example of what you mean, in a loop situation? Thanks.


PB - Registered PureBasic Coder
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by tranquil.

If InitNetwork() = 0
MessageBox_ (0,"Failed to initialize TCP/IP Network","TCP/IP Error",#MB_ICONSTOP|#MB_OK)
End
EndIf

server=CreateNetworkServer(serverport)
If server=0
MessageBox_ (0,"Failed to create Network Server","TCP/IP Error",#MB_ICONSTOP|#MB_OK)
End
EndIf

If OpenWindow(0,winx,winy,winw,winh,#Flags,winname$) = 0
MessageBox_ (0,"Failed to open window","Windows Error",#MB_ICONSTOP|#MB_OK)
End
EndIf

If WSAAsyncSelect_(server,UseWindow(0),1000,#FD_ACCEPT|#FD_READ|#FD_WRITE|#FD_OOB|#FD_CONNECT)=0:EndIf ; Get Serverevents as message 1000



Repeat

If winevent.l=0:waitmessage_():EndIf
winevent.l=WindowEvent()
wineventgadget.l=EventGadgetID()
serverevent.l=NetworkServerEvent()

; MENU EVENTS

If winevent.l=#PB_EventMenu

EndIf

; GADGET EVENTS

If winevent = #PB_EventCloseWindow : esc=1 : EndIf

.....your code here....

until esc=1

end


Only a short codesnip out of my server source


Tranquilizer/ Secretly!
Registred PureBasic User
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by PB.

> If winevent.l=0:waitmessage_():EndIf
> winevent.l=WindowEvent()

But how is this different to just using: winevent.l=WaitWindowEvent() ?
It isn't, as far as I can tell. And therefore, like I said, if you're
not waiting for a Window event, then using Sleep_(1) seems to be the
only way to reduce the CPU load... correct?


PB - Registered PureBasic Coder
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by tranquil.

It makes sense if you want to receive events that WaitWindowEvent did not act on. For eg. Network-Events. I'm using this to wait for messages or incoming connections to the server.
I needed to add an "Socket-Event"-ID to the Window by doing this:

WSAAsyncSelect_(server,UseWindow(0),1000,#FD_ACCEPT|#FD_READ|#FD_WRITE|#FD_OOB|#FD_CONNECT)

A wait message reports EVERY event that ocurs in a window. (eg Cursor-Blinking in a String-Gadget that we need very often.

Cheers!

Tranquilizer/ Secretly!
Registred PureBasic User
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by Steve.


PB
How about WindowEvent ? It works the same as the api PeekMessage
It dosn't wait for a message, just peeks at the message loop.
;Don't wait for any messages
While WindowEvent() #PB_EventCloseWindow
dosomething
Wend

Steve.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by PB.

> It makes sense if you want to receive events that WaitWindowEvent did not act on.

Okay, but what about apps that don't need events -- apps that don't even
create a window in the first place? Such as an app that creates a file at
a regular interval? You can't use WindowEvent() or WaitMessage_ with these,
because no window was created -- right?


PB - Registered PureBasic Coder

Edited by - PB on 25 April 2002 08:03:32
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by tinman.
Okay, but what about apps that don't need events -- apps that don't even
create a window in the first place? Such as an app that creates a file at
a regular interval? You can't use WindowEvent() or WaitMessage_ with these,
because no window was created -- right?
I think WaitMessage_ waits for a message to be added to a thread's message queue (according to the MS SDK I have). It does not mention windows at all so I don't think it has to be a window (why would you need a window to get network, file or timer messages?).


--
It's not minimalist - I'm increasing efficiency by reducing input effort.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by skypa.

Is 'delay(x)' equal to 'sleep_(x)' ?
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by tinman.
Is 'delay(x)' equal to 'sleep_(x)' ?
No, 'Delay_(x)' (with underscore - it is an API call) sends your program to sleep for x 50ths of a second. The x in 'Sleep_(x)' is the number of milliseconds to make your program sleep for (0 in this case means to give up the remainder of the time slice).

Also, just to add some more fuel to the fire, the MS SDK I have here says it is preferable to use MsgWaitForMultipleObjects_ instead of Sleep_.


--
It's not minimalist - I'm increasing efficiency by reducing input effort.
BackupUser
PureBasic Guru
PureBasic Guru
Posts: 16777133
Joined: Tue Apr 22, 2003 7:42 pm

Post by BackupUser »

Restored from previous forum. Originally posted by tranquil.

It must be possible to wait for ANY event that happens on a system.
MsgWaitForMultipleObjects_ listens nice for such things. :)

Mike

Tranquilizer/ Secretly!
Registred PureBasic User
Post Reply