Minimal delay in Pharo...

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

Minimal delay in Pharo...

Thierry Goubier
Hi all,

anybody knows if, when doing something like:

(Delay forMilliseconds: n) wait

It is possible for the Delay to return immediately if n is small enough
or do we have a guaranteed behavior of at least a 'yield' equivalent?

I'm looking into active polling for parallel stuff and I noticed that a
busy loop with Processor yield may result in more or less locking the vm
since it only gives scheduling to processes which have a higher or equal
priority, so this is why I'm looking into using Delay wait instead. But
I'd like the delay to be as short as possible for performance reason
while allowing lower priority processes a chance to run.

Thanks,

Thierry


Reply | Threaded
Open this post in threaded view
|

Re: Minimal delay in Pharo...

Ben Coman
On Fri, Jun 12, 2015 at 1:00 AM, Thierry Goubier
<[hidden email]> wrote:
> Hi all,
>
> anybody knows if, when doing something like:
>
> (Delay forMilliseconds: n) wait
>
> It is possible for the Delay to return immediately if n is small enough or
> do we have a guaranteed behavior of at least a 'yield' equivalent?

For sufficiently small values of 'n', there will be no yield behaviour.

To follow the logic (assuming timingPriority > pollingPriority >
userPriority)...
1. Delay>>#wait calls DelayMicrosecondScheduler>>#schedule:   (your
pollingPriority process)
2. where "timingSemaphore signal"
3. passes control to  #runTimerEventLoop and #handleEventTimer:
(running in the timingPriority process)
4. which invokes #scheduleDelay: to add your delay to /suspendedDelays/
5. back in #handleEventTimer:  "Signal any expired delays" cycles
through /suspendedDelays/ such that if 'n' time has passed your
delay's delaySemaphore is immediately signalled, then
6. control returns to #schedule:  (your pollingPriority process)
7. and thence to #wait: which does "delaySemaphore wait" -- but this
has already been signalled, so it zooms straight without any chance to
yield.

If you want to ensure yield behaviour I would add the obvious...
   Delay>>waitWithYield
      self wait.
      Processor yield.

However for other sufficiently low values 'n2' (n2>n), not enough
lines of the userPriority process will be executed before your
pollingPriority process takes of, so the UI will effectively be locked
again.

Perhaps what is needed is for your polling process to observe the
/lastCycleTime/ ivar set by   WorldState>>interCyclePause:   and
dynamically adjust your polling interval to keep lastCycleTime at a
reasonable value.

cheers -ben

> I'm looking into active polling for parallel stuff and I noticed that a busy
> loop with Processor yield may result in more or less locking the vm since it
> only gives scheduling to processes which have a higher or equal priority, so
> this is why I'm looking into using Delay wait instead. But I'd like the
> delay to be as short as possible for performance reason while allowing lower
> priority processes a chance to run.
>
> Thanks,
>
> Thierry
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Minimal delay in Pharo...

Thierry Goubier
Le 12/06/2015 04:08, Ben Coman a écrit :

> On Fri, Jun 12, 2015 at 1:00 AM, Thierry Goubier
> <[hidden email]> wrote:
>> Hi all,
>>
>> anybody knows if, when doing something like:
>>
>> (Delay forMilliseconds: n) wait
>>
>> It is possible for the Delay to return immediately if n is small enough or
>> do we have a guaranteed behavior of at least a 'yield' equivalent?
>
> For sufficiently small values of 'n', there will be no yield behaviour.
>
> To follow the logic (assuming timingPriority > pollingPriority >
> userPriority)...
> 1. Delay>>#wait calls DelayMicrosecondScheduler>>#schedule:   (your
> pollingPriority process)
> 2. where "timingSemaphore signal"
> 3. passes control to  #runTimerEventLoop and #handleEventTimer:
> (running in the timingPriority process)
> 4. which invokes #scheduleDelay: to add your delay to /suspendedDelays/
> 5. back in #handleEventTimer:  "Signal any expired delays" cycles
> through /suspendedDelays/ such that if 'n' time has passed your
> delay's delaySemaphore is immediately signalled, then
> 6. control returns to #schedule:  (your pollingPriority process)
> 7. and thence to #wait: which does "delaySemaphore wait" -- but this
> has already been signalled, so it zooms straight without any chance to
> yield.
>
> If you want to ensure yield behaviour I would add the obvious...
>     Delay>>waitWithYield
>        self wait.
>        Processor yield.
>
> However for other sufficiently low values 'n2' (n2>n), not enough
> lines of the userPriority process will be executed before your
> pollingPriority process takes of, so the UI will effectively be locked
> again.
>
> Perhaps what is needed is for your polling process to observe the
> /lastCycleTime/ ivar set by   WorldState>>interCyclePause:   and
> dynamically adjust your polling interval to keep lastCycleTime at a
> reasonable value.

Thanks Ben for the analysis. I suspected something like that could
happen, and I'm happy to have the confirmation.

Thierry