1. Multitasking in Mac OS Gets 100% CPU
- Posted by bryanso Nov 05, 2012
- 1601 views
The following naive implementation of get_key with multitasking support causes 100% CPU in Mac OS (Mountain Lion, Eu 4.0.4). Is there a better practice? This does not cause high CPU usage in Windows 7.
Is there something I can do in Mac OS to reduce the CPU consumption?
function editor_wait_key() atom c = -1 while c = -1 do c = get_key() task_yield() end while return c end function
Changing task_yield to task_delay or even sleep still has the same problem:
function editor_wait_key() atom c = -1 while c = -1 do c = get_key() task_delay(0.05) -- sleep(0.01) end while return c end function
Thanks
2. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by mattlewis (admin) Nov 05, 2012
- 1541 views
The following naive implementation of get_key with multitasking support causes 100% CPU in Mac OS (Mountain Lion, Eu 4.0.4). Is there a better practice? This does not cause high CPU usage in Windows 7.
Is there something I can do in Mac OS to reduce the CPU consumption?
It's hard to say without seeing more of your code. Where does execution go when you call task_yield()? get_key() returns immediately. There's nothing there really that would lead me to believe that you'd get anything but 100% utilization until a key is pressed.
Matt
3. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by ryanj Nov 05, 2012
- 1535 views
What happens when you use a longer delay? Such as:
task_delay(5)
Does it still use 100% CPU?
4. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by bryanso Nov 05, 2012
- 1536 views
I'll trim my test case down to a more manageable size and post the code. (I believe nothing has been scheduled, though, so task_yield really has nothing to do).
Hi Ryan, I think I can't use task_delay(5) in a loop that's getting user input. The user will feel the keyboard is sluggish.
Thanks all.
What happens when you use a longer delay? Such as:
task_delay(5)
Does it still use 100% CPU?
5. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by ryanj Nov 05, 2012
- 1543 views
My point was to try it temporarily for troubleshooting, just to see if task_delay() itself was using 100% CPU.
6. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by mattlewis (admin) Nov 05, 2012
- 1557 views
Hi Ryan, I think I can't use task_delay(5) in a loop that's getting user input. The user will feel the keyboard is sluggish.
If you're not really doing anything else, and this is a console program, then you should probably be using wait_key().
Matt
7. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by bryanso Nov 05, 2012
- 1550 views
Hi Matt, thanks for the suggestion. It's a command shell so it's waiting for user to run something in the background, e.g. in Unix shell, one can put an & at the end of a command to run it in the background.
Ideally the input routine doesn't need to be written in two ways: wait_key when nothing is running in background; switch to get_key when there is a background job, and somehow switch back to wait_key when the background jobs complete. That's very complicated.
Again, I'll post a streamlined test case later, which will make it clear.
Hi Ryan, I think I can't use task_delay(5) in a loop that's getting user input. The user will feel the keyboard is sluggish.
If you're not really doing anything else, and this is a console program, then you should probably be using wait_key().
Matt
8. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by bryanso Nov 06, 2012
- 1510 views
Hi Matt,
The simplest case is the multitasking example in mini guide http://openeuphoria.org/docs/tasking.html#_645_multitaskingineuphoria
When it is run in Mac OS Mountain Lion, EU 4.0.4, the cpu goes up to 100% during the entire execution.
I don't believe this is expected as it doesn't have the same problem in Windows 7.
In a command shell application as I explained above, even when there is no scheduled background task, the cpu goes up to 100% during user data entry.
This happens only in Mac OS.
Thanks
9. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by mattlewis (admin) Nov 06, 2012
- 1494 views
Hi Matt,
The simplest case is the multitasking example in mini guide http://openeuphoria.org/docs/tasking.html#_645_multitaskingineuphoria
When it is run in Mac OS Mountain Lion, EU 4.0.4, the cpu goes up to 100% during the entire execution.
I don't believe this is expected as it doesn't have the same problem in Windows 7.
I get this behavior on Linux. I would expect Windows to show the same thing. Most of the time is spent in the while loop:
while t1_running or t2_running do if get_key() = 'q' then exit end if task_yield() end while
The other tasks don't run very often, so control returns here. When you yield here, control typically comes right back, because the other tasks aren't ready to run yet.
I tried this in WinXP, and I think it's actually using all of the CPU there, but some of it is reported for csrss.exe. The multitasking on Windows is implemented with Fibers, and I think that Fiber related activity shows up under csrss.exe. The CPU is definitely pegged while the program is running.
Matt
10. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by bryanso Nov 06, 2012
- 1465 views
I don't have XP for testing. In Windows 7 the CPU usage is really awesome. Same multitask sample code, except I changed the For loops to 100 for longer run time.
csrss.exe between 1% to 7%
eui between 2% to 5%
Nothing else is out of the ordinary.
I do understand having a while loop doing get_key() is probably CPU intensive. So I'm merely looking for ideas for a better coding practice to code a "get_line" routine that's suitable as Shell command input, sometimes with background processes, sometimes not (just like a Unix shell)... without taking up 100% CPU in Linux and Mac OS. The Mac gets hot and the fan starts fanning as soon as the multitask sample is run.
I'll try task_delay within the get_key loop again tonight using the multitask sample code in Mac and report.
11. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by ghaberek (admin) Nov 06, 2012
- 1446 views
I get this behavior on Linux. I would expect Windows to show the same thing. Most of the time is spent in the while loop:
while t1_running or t2_running do if get_key() = 'q' then exit end if task_yield() end while
The other tasks don't run very often, so control returns here. When you yield here, control typically comes right back, because the other tasks aren't ready to run yet.
I tried this in WinXP, and I think it's actually using all of the CPU there, but some of it is reported for csrss.exe. The multitasking on Windows is implemented with Fibers, and I think that Fiber related activity shows up under csrss.exe. The CPU is definitely pegged while the program is running.
On Linux, throwing sleep(1) into the main loop seems to keep the CPU usage under control (practically 0%). Using sleep(0) or any fraction < 1 (e.g. sleep(0.01)) has no effect and the CPU still spikes to 100%.
while t1_running or t2_running do if get_key() = 'q' then exit end if task_yield() sleep(1) -- toggle between 0 or 1 and observe the outcome end while
Interestingly, checking gnome-system-monitor with sleep(1) the "Waiting Channel" column displays hrtimer_nanosleep, but with sleep(0) it simply shows "0". Is the sleep() function not calling "nanosleep" when we pass 0 as a parameter?
-Greg
12. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by useless_ Nov 06, 2012
- 1449 views
I get this behavior on Linux. I would expect Windows to show the same thing. Most of the time is spent in the while loop:
while t1_running or t2_running do if get_key() = 'q' then exit end if task_yield() end while
The other tasks don't run very often, so control returns here. When you yield here, control typically comes right back, because the other tasks aren't ready to run yet.
I tried this in WinXP, and I think it's actually using all of the CPU there, but some of it is reported for csrss.exe. The multitasking on Windows is implemented with Fibers, and I think that Fiber related activity shows up under csrss.exe. The CPU is definitely pegged while the program is running.
On Linux, throwing sleep(1) into the main loop seems to keep the CPU usage under control (practically 0%). Using sleep(0) or any fraction < 1 (e.g. sleep(0.01)) has no effect and the CPU still spikes to 100%.
That there are spikes to 100% is almost expected. It's the long time between the spikes when it's sleeping that cpu should go to 0%.
useless
13. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by jimcbrown (admin) Nov 06, 2012
- 1463 views
Interestingly, checking gnome-system-monitor with sleep(1) the "Waiting Channel" column displays hrtimer_nanosleep, but with sleep(0) it simply shows "0". Is the sleep() function not calling "nanosleep" when we pass 0 as a parameter?
-Greg
Looks like we have a bug in Wait() in be_task.c (which is used to implement the sleep() routine).
We have code in there to busy-wait if we are attempting to sleep in fractional sections, and the fractions are too small - but we also have a check so if we're sleeping for less than 1 second we just busy-wait it out.
I think this was done back when we supported DOS so we could sleep for fractional seconds from DOS apps...
14. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by ghaberek (admin) Nov 06, 2012
- 1428 views
That there are spikes to 100% is almost expected. It's the long time between the spikes when it's sleeping that cpu should go to 0%.
I meant spikes as in "goes from almost zero to almost 100% very quickly." I suppose plateaus might be more appropriate, since after it gets to 100% it also stays there until the program exits. This would be the opposite of say, climbs, which would be "gradually increases from zero to 100% over several seconds."
I think this was done back when we supported DOS so we could sleep for fractional seconds from DOS apps...
So, if you're actually calling to nanosleep, you could pass that fraction directly to it, correct?
-Greg
15. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by jimcbrown (admin) Nov 07, 2012
- 1424 views
I think this was done back when we supported DOS so we could sleep for fractional seconds from DOS apps...
So, if you're actually calling to nanosleep, you could pass that fraction directly to it, correct?
-Greg
Yes, we could. (Technically, we'd have to convert it to a set of integer values, one of which representing the micro/nanosecond value, and then pass that in - but same difference.) And in theory we'd have to busy-wait if we wanted to be able to sleep any leftover fractional value - but at such a low range, I doubt busy-waiting would make much of a difference anyways.
16. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by mattlewis (admin) Nov 07, 2012
- 1433 views
Interestingly, checking gnome-system-monitor with sleep(1) the "Waiting Channel" column displays hrtimer_nanosleep, but with sleep(0) it simply shows "0". Is the sleep() function not calling "nanosleep" when we pass 0 as a parameter?
-Greg
Looks like we have a bug in Wait() in be_task.c (which is used to implement the sleep() routine).
We have code in there to busy-wait if we are attempting to sleep in fractional sections, and the fractions are too small - but we also have a check so if we're sleeping for less than 1 second we just busy-wait it out.
I think this was done back when we supported DOS so we could sleep for fractional seconds from DOS apps...
I just profiled this (on Linux) and I don't see Wait() being called at all (though I agree that we should probably move all of the waiting time in Wait() into the nanosleep call). If you add a print statement after the call to get_key(), you'll see that a lot of time is spent going around in that loop.
Most of the time is spent in nodelaych() (and really, in a call to tcsetattr), which is how we get keyboard input in non-windows systems. Windows works differently. So perhaps Win7 has a more efficient way of handling console input than XP. Perhaps our implementation of nodelaych() could be improved. Do we really need to call tcsetattr() each time we call get_key()?
Matt
17. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by mattlewis (admin) Nov 07, 2012
- 1402 views
Most of the time is spent in nodelaych() (and really, in a call to tcsetattr), which is how we get keyboard input in non-windows systems. Windows works differently. So perhaps Win7 has a more efficient way of handling console input than XP. Perhaps our implementation of nodelaych() could be improved. Do we really need to call tcsetattr() each time we call get_key()?
I took out the tcsetattr() call in nodelaych(), which changed the profiling, but not the CPU usage. Most time is being spent in the task scheduler() routine, which isn't surprising, since task_yield() was called over 1.5 million times.
In short, I don't think there is really any problem here. A busy loop should produce 100% CPU usage.
Matt
18. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by ghaberek (admin) Nov 07, 2012
- 1434 views
In short, I don't think there is really any problem here. A busy loop should produce 100% CPU usage.
While I agree that a simple busy loop should produce 100% CPU usage, I think that a tasking loop with regular calls to sleep() should not, since the OS has the opportunity to schedule other programs.
-Greg
19. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by jimcbrown (admin) Nov 07, 2012
- 1388 views
In short, I don't think there is really any problem here. A busy loop should produce 100% CPU usage.
While I agree that a simple busy loop should produce 100% CPU usage, I think that a tasking loop with regular calls to sleep() should not, since the OS has the opportunity to schedule other programs.
-Greg
This raises the question: How does one go about implementing a non-busy-looping version of wait_key() that allows other tasks to run while waiting for a key press?
20. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by mattlewis (admin) Nov 07, 2012
- 1415 views
In short, I don't think there is really any problem here. A busy loop should produce 100% CPU usage.
While I agree that a simple busy loop should produce 100% CPU usage, I think that a tasking loop with regular calls to sleep() should not, since the OS has the opportunity to schedule other programs.
Well, yes, there's that. Looking deeper, I suspect that Jim is right about the busy loop for sleeps of less than a second being a DOS hold over, since nanosleep() and Windows' sleep() work with fractional seconds.
Matt
21. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by mattlewis (admin) Nov 07, 2012
- 1460 views
This raises the question: How does one go about implementing a non-busy-looping version of wait_key() that allows other tasks to run while waiting for a key press?
I updated Wait() to use nanosleep for all values, then I put the input loop into its own task and scheduled the main task. So, added to the example code (I also added code to output keystrokes other than 'q' to demonstrate responsiveness):
procedure input_task( object o ) integer key while key != 'q' with entry do if key != -1 then puts(1, key ) end if task_yield() entry key = get_key() end while t3_running = FALSE end procedure t3 = task_create(routine_id("input_task"), {""}) task_schedule(t3, {0.001, 0.05}) task_schedule( task_self(), {0.1, 0.5}) t1_running = TRUE t2_running = TRUE t3_running = TRUE while t3_running and (t1_running or t2_running) do task_yield() end while
This reduces the CPU load such that it's not really noticeable (for this minimal example that doesn't do anything).
Matt
22. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by bryanso Nov 07, 2012
- 1407 views
This demonstrates task_delay has a bug. CPU remains at 100% even though the main loop and the thread both generously allow lots of delay:
include std/task.e integer t1_running procedure task1(sequence message) for i = 1 to 100 do printf(1, "task1 (%d) %s\n", {i, message}) task_delay(1) end for t1_running = 0 end procedure atom t1 = task_create(routine_id("task1"), {"Hello"}) task_schedule(t1, 10) t1_running = 1 while t1_running do if get_key() = 'q' then exit end if task_delay(5) end while
23. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by mattlewis (admin) Nov 08, 2012
- 1390 views
This demonstrates task_delay has a bug. CPU remains at 100% even though the main loop and the thread both generously allow lots of delay:
This is fixed. See ticket:819.
Matt
24. Re: Multitasking in Mac OS Gets 100% CPU
- Posted by bryanso Nov 08, 2012
- 1359 views
This demonstrates task_delay has a bug. CPU remains at 100% even though the main loop and the thread both generously allow lots of delay:
This is fixed. See ticket:819.
Matt
Thanks a lot. Awesome.