CPU usage

Submitted by vvdleun on Tue, 09/24/2013 - 16:17

Hi,

I think the issue that should be on top of True BASIC´s to-do list should be fixing the high CPU usage issue.

The reason for this issue is quite clear. TB is constantly looking for Windows events, as John Arscott said here previously as well. This message pump loop should have been programmed to wait for events and handle the incoming ones instead of polling ("peeking") for events all the time. Of course, I don't know if this part of the source code is or is not available to the current owners of True BASIC and if anyone can compile the code.

As is described in this topic http://www.truebasic.com/node/832 , doing a short pause helps. True BASIC's pause statement most probably converts the specified value to milliseconds and calls the Sleep Win32 API (http://msdn.microsoft.com/en-us/library/windows/desktop/ms686298(v=vs.85).aspx). As documented in the specified URL, this function causes a thread to relinquish the remainder of its time slice. So basically other threads are given time to run.

Specifying 0ms does not help (I tested it, even by creating a DLL in a different language to make sure that it actually runs). The trouble with sleep(0) is that this function immediately returns and put simply (probably not 100% technically correct) it does not give Windows/CPU time to "breathe", as it will still run the loop if no other thread is waiting (so still using 100% of a CPU core). For those interested, I found more information here: http://stackoverflow.com/questions/3727420/significance-of-sleep0

I wish I could come up with a good solution, but after studying the Win32 API I fear it will only be possible by changing the original source code.

The next best thing should be to call sleep(1) every now and again, as was suggested in the TB forum posting that I linked to. Instead of every loop iteration I'd suggest to do it in a counter. Some stupid code that I used to test the DEMTXED editor example with:

Somewhere in the beginning:
LET I=0
...DO....
....
LET I = I + 1
IF I > 1024 THEN
PAUSE 0.01
LET I = 0
END IF

...LOOP...

The result on my laptop (Win 7) was quite good. Very low CPU usage and to me the application was quite responsive (I am a quick typist). Of course above´s snippet should be improved.

Did anyone try something like this in a real-world TB application and can share their experience?

BTW: I *don't* want to suggest that the original developers of this part of TB did a lousy or bad job. There's most probably a lot going on "under the hood" of TB's message loop. Talking about changing it is probably much easier than actually doing it.

I agree that 100% CPU usage is an annoying feature of TB programs. Basically it all boils down to the use of the routine TC_event, which itself calls the built-in subroutine SYS_EVENT. As you correctly observed, if these sub-routines are placed in a DO...LOOP then the loop will continuously cycle - hence the 100% CPU usage, regardless of whether any "events" are actually happening.

As you also correctly observed, one possible solution might be to PAUSE the continuous cycle, but there is a problem with this method, i.e. how often, and for how long?

There are basically two types of event; mouse and keyboard. It is possible to write your own routine to mimic the SYS_EVENT routine, by using IF KEY INPUT (followed by GET KEY) and GET MOUSE. The advantage with SYS_EVENT is that the events form a queue - at least this is what the manual says. Looping through SYS_EVENT allows us to inspect the queue until it is exhausted. In some programs, such as the TBeditor, it is necessary to empty or flush out the queue.

If we decide to introduce a PAUSE in the loop, we have to make sure we don't miss any "events". Take for example a double mouse click. The manual doesn't say what the time interval is between the two clicks, but in practice if you are too slow you get two "SINGLE" events instead of a "DOUBLE". Likewise, if hold a key down, then you will get multiple instances of "KEYPRESS" events. The number will depend on how your keyboard has been set up. Obviously a pause inside the event loop might cause us to miss some mouse clicks or keypresses, although we could add some logic that says a pause cannot occur if an event is already in the queue and that a pause can only occur when the queue is empty.

Unfortunately the manual is not very explicit about the way the event queue works. What I don't know is whether this queue accumulates events even if we are not currently cycling through the loop. If it does queue events regardless, then the duration of the PAUSE largely depends on whether the user will notice a slight delay. Maybe somebody can experiment and find out how long the PAUSE can be before someone will notice.

If we can devise a workable pause system, then I will be quite happy to include an alternative low CPU version of TC_event in the True Ctrl library module, and to modify the TBeditor accordingly.

The docs promise that TC_Event will still return immediately if there are events to process and otherwise wait for them. This sounds better than using the Pause statement.

I tried some examples. If I used the 0.5 value (IIRC) I had good results, anything lower and the CPU was back to 100%. I found the scrollbar performance acceptable myself. I assume using timer is incompatible with the event list emptying technique John mentioned, though. For my first TB app I'm going to experiment with this parameter.

On an unrelated note, does anybody know an URL to download a reasonable sized TB app, so I can do easier testing with the CPU?
Of course, I *should* be writing those apps myself.... :-)

The only issue I see with putting in a pause directly or in a loop like you have done is that the scroll bars do not respond correctly. I am still hoping that someone at TB can come up with a fix for the offending library.

Yes, I saw some graphical issues as well, I believe in the menu bar.
However, on my laptop I seem to have some issues (flickering mouse cursor) when I'm running the standard TB code without modifications as well.

I also truly hope that the existing TB code can be fixed. This would be a win-win situation for everyone.

If not, there's one other solution that I can think of and that is rewriting the "OBJECT" routine in a DLL. Or at least the most important portions of it, to form a new alternative GUI library. Would be a massive undertaking though.

For fun I'm gonna to toy with this idea, but don't expect any meaningful code from me anytime soon.
Just like to play with this idea, to see if it is possible at all and see where the complications are.

There are many reasons for re-writing the OBJECT code. For example, to give greater control over colors, text formats and the like. Some years ago I did this and produced a library module called CTX which re-created all the existing objects, including menus, push buttons, text boxes, image boxes, lists etc., plus a whole lot more including dialog boxes. This was all done from scatch using TB graphics only and no Windows APIs. The only things I did borrow from the TrueCtrl library was TC_win_create and TC event. This was indeed a MASSIVE undertaking.

In the CTX library ALL objects are clickable with the mouse and all return "SINGLE" as the event. CTX_event also returns the type of object, e.g. push button, list, image etc. All other events are passed on as is, e.g. typed character numbers. In this way CTX and TrueCTRL can co-exist in the same program. The Version 6 editor works this way.

It is relatively easy to use PAUSE or the TC_event (timer) parameter within either CTX or TrueCtrl to reduce CPU usage provided we all agree on the value of the time pause. We can even introduce a routine called Reduced_CPU(value) which will allow users to set a global variable for the pause time. We can even automatically add some code to users programs that will set this pause time. We also need to define a way of measuring the reduction in CPU usage so that users can witness the improvement. Any ideas?

Sorry but a bit of a sidetrack from the original question but have there been any updates to the CTX library recently. You said a while back that you were going to implement additional controls and I was just wondering how that was coming along.

Recently I have modified the Stext and Pushbutton control objects so that they will accept images as well as text. This is important for languages such as Chinese, Japanese and Korean, and for any Unicode fonts. As you know, TB only recognizes ANSI fonts which are limited to 255 characters.