Re: [Vm-dev] Use less CPU (improve battery life or reduce cost in the cloud)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] Use less CPU (improve battery life or reduce cost in the cloud)

Bert Freudenberg
I think nowadays we could actually switch to a fully event/timer driven main loop for Morphic without major drawbacks. This was not true when Morphic was designed, since the VM back then was not event-based.

Instead of a fixed interCyclePause we simply need to wait on a semaphore that should get signaled when a new event is available, and timed-out when the next Morphic alarm / step message is due. It probably also needs to be triggered when a deferred UI message is added.

On the VM side, we would need to replace relinquishProcessorForMicroseconds with something like goToSleep. This primitive would block the VM completely until the ActiveDelay expires or some other event occurred (input, file becomes readable, socket data available etc).

The advantage of this would be, as Holger wrote, that we would become a lot more battery-efficient, since we would wake up only if there is actual work to do.

- Bert -

On Wed, Aug 30, 2017 at 7:56 AM, Marcel Taeumel <[hidden email]> wrote:
 
Hi Holger,

The Morphic main loop empties the event queue (mouse & keyboard) in each cycle. It also checks for drawing requests and stepping. If that processing goes too fast, it tries to free CPU time via a delay (so that the idle process can run if no other).

No, it does not make sense to get rid of that pause/delay/tick. ;-) The system is NOT event-based at that lower level. It is just polling/looping. A single UI process, which sleeps occasionally. By design.

Note that if you want to run that in the cloud, just avoid busy morphs and Morphic should use very little CPU resources.

Best,
Marcel

Am 29.08.2017 23:29:21 schrieb Holger Freyther <[hidden email]>:


Hi,

I have done some early prototype for the Unix VM end of 2015(?) and I have improved and repeated these for MacOS now and the thread based heartbeat (now that it is the universal default). I won't make it to ESUG this year but this might be something to play with?

The motivations is simple: Polling increases the CPU usage which will reduce your battery life, takes away resources from other processes (e.g. more Pharo images) or these days increases your cloud computing bill. On top of that it might increase network latency (time from socket becoming readable to the time the semaphore is signaled).

To complete the work we have work inside the Image and the VM and some of it is on the way and others might need more discussion.


The idle process:

ProcessorScheduler>># idleProcess
"A default background process which is invisible."

[true] whileTrue:
[self relinquishProcessorForMicroseconds: 1000]

Let's please yield the CPU for more than a 1ms. Unless I am missing something an expired Delay or network IO would make us wake up earlier anyway?


The delay scheduler:

The VM supports that when the next wake-up time is set to 0, the VM can sleep indefinitely. There is a pending patch to sleep "0" in our Delay scheduler. Currently we force a wake-up earlier than that. I think we should trust the VM to do wake us up even if it is a second away.


Morphic UI:

I don't understand the WorldState>>#interCyclePause but then I never looked at Morphic. Do we really need to poll like that? Under which circumstances does the world update? We get an event (where we have the event semaphore), we get some I/O (where we have a semaphore) or we have a timeout (where we sleep on a semaphore). Did anyone ever look at removing the tick?


VM I/O:

Currently we receive a SIGIO but from what I can see (and I still need to write a benchmark) the processing might be delayed 20ms? My hack removes the usage of nextPollUsecs and instead checks a variable that is set by the SIGIO handler. Besides missing memory barriers this should work(tm).

The biggest issue seems that for macos/ios the input is driven by polling. E.g. some wheel events seem to require to pump the event queue. Is this something we could trigger from the image in the future? I had hoped to get a fd to a machport we could get SIGIO for.. but that doesn't seem to exist. I have hacked out the honoring of the relinquish delay, added the polling into a iOS specific routine and thanks to the Morphic Delay we bump the event loop frequently enough.


VM heartbeat thread:

The process keeps ticking even if the VM doesn't run. E.g. sleeps and waits for an event. There is a cost in deciding when to halt the thread so there must be a cut-off for which delays we bother to disable the heartbeat thread. I think the current code would allow the hearbeat to drift so the new code might just make it a bit worse.


Where are we now?

I have pushed my changes to https://github.com/zecke/opensmalltalk-vm/tree/mac-use-less-cpu and would be happy to have people look at it, look at the memory synchronization, maybe run to see if they notice extra delays or such?


I started the same image with the plain-vm and my hacked one and let it run for about 20min. The output is coming from top.

COMMAND %CPU TIME
Pharo 4.3 00:48.49
Pharo 0.8 00:10.20


Looking for comments and feedback.

regards
holger




Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] Use less CPU (improve battery life or reduce cost in the cloud)

Eliot Miranda-2
Hi Bert,


On Aug 30, 2017, at 8:36 AM, Bert Freudenberg <[hidden email]> wrote:

I think nowadays we could actually switch to a fully event/timer driven main loop for Morphic without major drawbacks. This was not true when Morphic was designed, since the VM back then was not event-based.

Instead of a fixed interCyclePause we simply need to wait on a semaphore that should get signaled when a new event is available, and timed-out when the next Morphic alarm / step message is due. It probably also needs to be triggered when a deferred UI message is added.

+1

On the VM side, we would need to replace relinquishProcessorForMicroseconds with something like goToSleep. This primitive would block the VM completely until the ActiveDelay expires or some other event occurred (input, file becomes readable, socket data available etc).

Yes, relinquishProcessorForMicroseconds should be eliminated.  The goToSleep primitive isn't necessary.  Instead the scheduler can automatically enter the sleep state when no process is runnable. Right now the VM is forced to exit with an error message when no runnable process exists, but that's a bad idea.  Instead we merely eliminate the background process altogether and modify the scheduler.  An existence proof is the VisualWorks VM that works like this also.  It is able to sleep efficiently when no processes are runnable.

When the scheduler discovers no runnable process exists it enters a wait state that blocks on events (including potential socket and file i/o) with a time out that expires at the next scheduled delay, if any.  This wait state must also be abortable via an internally generated event used, for example, when a callback occurs on some other thread.  On Windows this is possible by including a semaphore in (IIRC)MsgWaitForMultipleEvebts.  In unixes it is typically achieved by ensuring that select/poll/epoll/kqueue is interruptible and delivering a signal to interrupt it.

One concern is backward compatibility.  It may be possible for the VM to run both old and new schemes without additional state, simply relying on the occurrence or absence of a relinquishProcessorForMicroseconds call.  But more likely the VM would benefit from a flag telling it whether to exit or enter the wait state when the scheduler finds no runnable processes.  This switch can be removed in a later major release cycle.  The flag can be maintained in the same set as hat controlling whether process suspensions n causes a yield, et al.  I.e. the flag persists in the image and is controlled via vmParameterAt:put:.


The advantage of this would be, as Holger wrote, that we would become a lot more battery-efficient, since we would wake up only if there is actual work to do.

- Bert -

Best,
Eliot
_,,,^..^,,,_ (phone)

On Wed, Aug 30, 2017 at 7:56 AM, Marcel Taeumel <[hidden email]> wrote:
 
Hi Holger,

The Morphic main loop empties the event queue (mouse & keyboard) in each cycle. It also checks for drawing requests and stepping. If that processing goes too fast, it tries to free CPU time via a delay (so that the idle process can run if no other).

No, it does not make sense to get rid of that pause/delay/tick. ;-) The system is NOT event-based at that lower level. It is just polling/looping. A single UI process, which sleeps occasionally. By design.

Note that if you want to run that in the cloud, just avoid busy morphs and Morphic should use very little CPU resources.

Best,
Marcel

Am 29.08.2017 23:29:21 schrieb Holger Freyther <[hidden email]>:


Hi,

I have done some early prototype for the Unix VM end of 2015(?) and I have improved and repeated these for MacOS now and the thread based heartbeat (now that it is the universal default). I won't make it to ESUG this year but this might be something to play with?

The motivations is simple: Polling increases the CPU usage which will reduce your battery life, takes away resources from other processes (e.g. more Pharo images) or these days increases your cloud computing bill. On top of that it might increase network latency (time from socket becoming readable to the time the semaphore is signaled).

To complete the work we have work inside the Image and the VM and some of it is on the way and others might need more discussion.


The idle process:

ProcessorScheduler>># idleProcess
"A default background process which is invisible."

[true] whileTrue:
[self relinquishProcessorForMicroseconds: 1000]

Let's please yield the CPU for more than a 1ms. Unless I am missing something an expired Delay or network IO would make us wake up earlier anyway?


The delay scheduler:

The VM supports that when the next wake-up time is set to 0, the VM can sleep indefinitely. There is a pending patch to sleep "0" in our Delay scheduler. Currently we force a wake-up earlier than that. I think we should trust the VM to do wake us up even if it is a second away.


Morphic UI:

I don't understand the WorldState>>#interCyclePause but then I never looked at Morphic. Do we really need to poll like that? Under which circumstances does the world update? We get an event (where we have the event semaphore), we get some I/O (where we have a semaphore) or we have a timeout (where we sleep on a semaphore). Did anyone ever look at removing the tick?


VM I/O:

Currently we receive a SIGIO but from what I can see (and I still need to write a benchmark) the processing might be delayed 20ms? My hack removes the usage of nextPollUsecs and instead checks a variable that is set by the SIGIO handler. Besides missing memory barriers this should work(tm).

The biggest issue seems that for macos/ios the input is driven by polling. E.g. some wheel events seem to require to pump the event queue. Is this something we could trigger from the image in the future? I had hoped to get a fd to a machport we could get SIGIO for.. but that doesn't seem to exist. I have hacked out the honoring of the relinquish delay, added the polling into a iOS specific routine and thanks to the Morphic Delay we bump the event loop frequently enough.


VM heartbeat thread:

The process keeps ticking even if the VM doesn't run. E.g. sleeps and waits for an event. There is a cost in deciding when to halt the thread so there must be a cut-off for which delays we bother to disable the heartbeat thread. I think the current code would allow the hearbeat to drift so the new code might just make it a bit worse.


Where are we now?

I have pushed my changes to https://github.com/zecke/opensmalltalk-vm/tree/mac-use-less-cpu and would be happy to have people look at it, look at the memory synchronization, maybe run to see if they notice extra delays or such?


I started the same image with the plain-vm and my hacked one and let it run for about 20min. The output is coming from top.

COMMAND %CPU TIME
Pharo 4.3 00:48.49
Pharo 0.8 00:10.20


Looking for comments and feedback.

regards
holger





Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] Use less CPU (improve battery life or reduce cost in the cloud)

timrowledge
Whilst thinking about this let us please keep in mind leaving some hooks for use cases where there is no interrupt-type incoming events - older OSs (<cough>RISC OS, Mac OS 9, Windows pre-whatever) or bare-metal systems with essentially no OS. I don’t think either case should prevent us moving forward but at least leaving open, clean, avenues for them to keep working would be nice.

tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
You can't make a program without broken egos.



Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] Use less CPU (improve battery life or reduce cost in the cloud)

Eliot Miranda-2
Hi Tim,

> On Aug 30, 2017, at 10:39 AM, tim Rowledge <[hidden email]> wrote:
>
> Whilst thinking about this let us please keep in mind leaving some hooks for use cases where there is no interrupt-type incoming events - older OSs (<cough>RISC OS, Mac OS 9, Windows pre-whatever) or bare-metal systems with essentially no OS. I don’t think either case should prevent us moving forward but at least leaving open, clean, avenues for them to keep working would be nice.

IMO, leaving it up to the VM to decide what to do when there's nothing to do allows better support on those other OSs and bare metal than leaving it up to the image to provide some catch all hack like the background process calling relinquishProcessorForMilliseconds.

>
> tim
> --
> tim Rowledge; [hidden email]; http://www.rowledge.org/tim
> You can't make a program without broken egos.
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] Use less CPU (improve battery life or reduce cost in the cloud)

timrowledge

> On 30-08-2017, at 12:14 PM, Eliot Miranda <[hidden email]> wrote:
>
> Hi Tim,
>
>> On Aug 30, 2017, at 10:39 AM, tim Rowledge <[hidden email]> wrote:
>>
>> Whilst thinking about this let us please keep in mind leaving some hooks for use cases where there is no interrupt-type incoming events - older OSs (<cough>RISC OS, Mac OS 9, Windows pre-whatever) or bare-metal systems with essentially no OS. I don’t think either case should prevent us moving forward but at least leaving open, clean, avenues for them to keep working would be nice.
>
> IMO, leaving it up to the VM to decide what to do when there's nothing to do allows better support on those other OSs and bare metal than leaving it up to the image to provide some catch all hack like the background process calling relinquishProcessorForMilliseconds.

No argument there. I won’t even argue that RISC OS is an important case these days, and that’s possibly the last in-use OS that requires the vm to be ‘in charge’ whilst running and to voluntarily surrender control in order to keep things going. I’d just like to make sure there is a small flag waving somewhere reminding us that there are systems we might want to support that are not unix/windows/mac.


tim
--
tim Rowledge; [hidden email]; http://www.rowledge.org/tim
Strange OpCodes: DNPG: Do Not Pass Go



Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] Use less CPU (improve battery life or reduce cost in the cloud)

David T. Lewis
On Wed, Aug 30, 2017 at 02:49:54PM -0700, tim Rowledge wrote:

>
> > On 30-08-2017, at 12:14 PM, Eliot Miranda <[hidden email]> wrote:
> >
> > Hi Tim,
> >
> >> On Aug 30, 2017, at 10:39 AM, tim Rowledge <[hidden email]> wrote:
> >>
> >> Whilst thinking about this let us please keep in mind leaving some hooks for use cases where there is no interrupt-type incoming events - older OSs (<cough>RISC OS, Mac OS 9, Windows pre-whatever) or bare-metal systems with essentially no OS. I don???t think either case should prevent us moving forward but at least leaving open, clean, avenues for them to keep working would be nice.
> >
> > IMO, leaving it up to the VM to decide what to do when there's nothing to do allows better support on those other OSs and bare metal than leaving it up to the image to provide some catch all hack like the background process calling relinquishProcessorForMilliseconds.
>
> No argument there. I won???t even argue that RISC OS is an important case these days, and that???s possibly the last in-use OS that requires the vm to be ???in charge??? whilst running and to voluntarily surrender control in order to keep things going. I???d just like to make sure there is a small flag waving somewhere reminding us that there are systems we might want to support that are not unix/windows/mac.
>

I for one think that RISC OS (or any other non-unix platform, take your
pick) remains an important use case. I personally think very highly of
Unix, and as the author of OSProcess I have taken an active role in making
platform specific functions available to Squeak images. But all the world
is not Unix. Never was, never will be, and never should be.

Smalltalk stands for a different way of thinking. It pains me every time
someone insists on adding a new platform-specific feature just because it
exists on Unix and maybe-sort-of works on Windows.

So bravo for RISC OS, SqueakNOS, SqueakJS, and Android VMs, keep them coming.

Dave