Delays should wakeup the idle process (patch)

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

Delays should wakeup the idle process (patch)

Tapple Gao
 
On my unix vm, Delay wakeups often happen a lot later than requested
if the idle process kicks in. Craig provided a bit of code from spoon
that fixes this issue:
http://bugs.squeak.org/view.php?id=7652
Reply | Threaded
Open this post in threaded view
|

Re: Delays should wakeup the idle process (patch)

Bert Freudenberg

On 15.07.2011, at 01:40, Matthew Fulmer wrote:

>
> On my unix vm, Delay wakeups often happen a lot later than requested
> if the idle process kicks in. Craig provided a bit of code from spoon
> that fixes this issue:
> http://bugs.squeak.org/view.php?id=7652

Very interesting.

On John's 4.x Mac VM I get 990 wakeups/sec.

Same for John's 5.7.4, 990/s.

But 5.8, and recent Cog/Stack VMs only do < 500 wakeups/sec. Both Carbon and Cocoa versions.

- Bert -


Reply | Threaded
Open this post in threaded view
|

Re: Delays should wakeup the idle process (patch)

Juan Vuletich-4
 
Bert Freudenberg wrote:

>  
> On 15.07.2011, at 01:40, Matthew Fulmer wrote:
>
>  
>> On my unix vm, Delay wakeups often happen a lot later than requested
>> if the idle process kicks in. Craig provided a bit of code from spoon
>> that fixes this issue:
>> http://bugs.squeak.org/view.php?id=7652
>>    
>
> Very interesting.
>
> On John's 4.x Mac VM I get 990 wakeups/sec.
>
> Same for John's 5.7.4, 990/s.
>
> But 5.8, and recent Cog/Stack VMs only do < 500 wakeups/sec. Both Carbon and Cocoa versions.
>
> - Bert -
>  
Right. Strangely, on recent Mac VMs, the behavior is not affected by
idle process / relinquish primitive. I turned Matthew's snippet into the
attached test. Another strange thing is that (on a recent Mac VM) this
test fails for 1mS and 5 mS, but passes for 2mS!

HTH.

Cheers,
Juan Vuletich

'From Cuis 3.3 of 2 June 2011 [latest update: #1024] on 15 July 2011 at 8:28:03 am'!
!classDefinition: #RelinquishPrimitiveTest category: #'Kernel-Tests'!
TestCase subclass: #RelinquishPrimitiveTest
        instanceVariableNames: ''
        classVariableNames: ''
        poolDictionaries: ''
        category: 'Kernel-Tests'!

!RelinquishPrimitiveTest methodsFor: 'testing' stamp: 'jmv 7/15/2011 08:25'!
testDelayAccuracy
        "
        RelinquishPrimitiveTest new testDelayAccuracy
        Test void relinquishPhysicalProcessor(void); in the VM.
        See http://bugs.squeak.org/view.php?id=7652
        See http://permalink.gmane.org/gmane.comp.lang.smalltalk.squeak.vm.devel/6381
        It appears that for some VMs, the relinquish primitiva takes too long to return?

        This should print a number close to 1000
        | tally delay morph updateDelay |
        tally := 0. delay := Delay forMilliseconds: 1.
        updateDelay := Delay forMilliseconds: 1000.
        morph := StringMorph new openInWorld.
        [[tally := tally + 1. delay wait] repeat] forkAt: 44.
        [[morph contents: tally printString. tally := 0. updateDelay wait] repeat] forkAt: 45.

        Evaluating this avoids the iddle process, and in some VMs (Linux) it seems to make the tally go from almost 500 to almost 1000.
        This trick doesn't seem to work on recent Mac VMs (the 4.2.4 Mac VM is always close 1000), as it is always a bit below 500
        [[] repeat] forkAt: 35
        "
        self testDelayAccuracy: 10.
        self testDelayAccuracy: 6.
        self testDelayAccuracy: 5.
        self testDelayAccuracy: 2.
        self testDelayAccuracy: 1! !

!RelinquishPrimitiveTest methodsFor: 'testing' stamp: 'jmv 7/15/2011 08:27'!
testDelayAccuracy: delayTime
        "
        RelinquishPrimitiveTest new testDelayAccuracy
        See comment there.
        "
        | tally delay updateDelay counter |
        tally _ 0.
        delay _ Delay forMilliseconds: delayTime.
        updateDelay _ Delay forMilliseconds: 1000.
        counter _ [[tally _ tally + 1. delay wait] repeat] newProcess.
        counter resumeAt: 44.
        tally _ 0.
        updateDelay wait.
        counter terminate.
        self assert: tally > (900/delayTime) description: 'Delay accuracy. Observed: ',
                (1000.0 / tally roundTo: 0.01) printString, ' mS. Requested: ', delayTime asFloat printString, ' mS.'! !
Reply | Threaded
Open this post in threaded view
|

Re: Delays should wakeup the idle process (patch)

johnmci

I'll see if can gather some historical thoughts on this later today

Sent from my iPhone

On 2011-07-15, at 7:47 AM, Juan Vuletich <[hidden email]> wrote:

>
> Bert Freudenberg wrote:
>> On 15.07.2011, at 01:40, Matthew Fulmer wrote:
>>
>>  
>>> On my unix vm, Delay wakeups often happen a lot later than requested
>>> if the idle process kicks in. Craig provided a bit of code from spoon
>>> that fixes this issue:
>>> http://bugs.squeak.org/view.php?id=7652
>>>    
>>
>> Very interesting.
>>
>> On John's 4.x Mac VM I get 990 wakeups/sec.
>>
>> Same for John's 5.7.4, 990/s.
>>
>> But 5.8, and recent Cog/Stack VMs only do < 500 wakeups/sec. Both Carbon and Cocoa versions.
>>
>> - Bert -
>>  
>
> Right. Strangely, on recent Mac VMs, the behavior is not affected by idle process / relinquish primitive. I turned Matthew's snippet into the attached test. Another strange thing is that (on a recent Mac VM) this test fails for 1mS and 5 mS, but passes for 2mS!
>
> HTH.
>
> Cheers,
> Juan Vuletich
> 'From Cuis 3.3 of 2 June 2011 [latest update: #1024] on 15 July 2011 at 8:28:03 am'!
> !classDefinition: #RelinquishPrimitiveTest category: #'Kernel-Tests'!
> TestCase subclass: #RelinquishPrimitiveTest
>    instanceVariableNames: ''
>    classVariableNames: ''
>    poolDictionaries: ''
>    category: 'Kernel-Tests'!
>
> !RelinquishPrimitiveTest methodsFor: 'testing' stamp: 'jmv 7/15/2011 08:25'!
> testDelayAccuracy
>    "
>    RelinquishPrimitiveTest new testDelayAccuracy
>    Test void relinquishPhysicalProcessor(void); in the VM.
>    See http://bugs.squeak.org/view.php?id=7652
>    See http://permalink.gmane.org/gmane.comp.lang.smalltalk.squeak.vm.devel/6381
>    It appears that for some VMs, the relinquish primitiva takes too long to return?
>
>    This should print a number close to 1000
>    | tally delay morph updateDelay |
>    tally := 0. delay := Delay forMilliseconds: 1.
>    updateDelay := Delay forMilliseconds: 1000.
>    morph := StringMorph new openInWorld.
>    [[tally := tally + 1. delay wait] repeat] forkAt: 44.
>    [[morph contents: tally printString. tally := 0. updateDelay wait] repeat] forkAt: 45.
>
>    Evaluating this avoids the iddle process, and in some VMs (Linux) it seems to make the tally go from almost 500 to almost 1000.
>    This trick doesn't seem to work on recent Mac VMs (the 4.2.4 Mac VM is always close 1000), as it is always a bit below 500
>    [[] repeat] forkAt: 35
>    "
>    self testDelayAccuracy: 10.
>    self testDelayAccuracy: 6.
>    self testDelayAccuracy: 5.
>    self testDelayAccuracy: 2.
>    self testDelayAccuracy: 1! !
>
> !RelinquishPrimitiveTest methodsFor: 'testing' stamp: 'jmv 7/15/2011 08:27'!
> testDelayAccuracy: delayTime
>    "
>    RelinquishPrimitiveTest new testDelayAccuracy
>    See comment there.
>    "
>    | tally delay updateDelay counter |
>    tally _ 0.
>    delay _ Delay forMilliseconds: delayTime.
>    updateDelay _ Delay forMilliseconds: 1000.
>    counter _ [[tally _ tally + 1. delay wait] repeat] newProcess.
>    counter resumeAt: 44.
>    tally _ 0.
>    updateDelay wait.
>    counter terminate.
>    self assert: tally > (900/delayTime) description: 'Delay accuracy. Observed: ',
>        (1000.0 / tally roundTo: 0.01) printString, ' mS. Requested: ', delayTime asFloat printString, ' mS.'! !
Reply | Threaded
Open this post in threaded view
|

Re: Delays should wakeup the idle process (patch)

johnmci

Ok, so after fiddling with this for the last decade let me had over
some words of advice

(a)  the relinquishPhysicalProcessor (whatever it's called) is passed
a value, this value is bogus magic meaningless number
(b) I did attempt to get that number from the Delay logic, but mmm
good luck, the last attempt killed images because it would deadlock on
a mutex semaphore lurking in Delay
(c) That led to the realization you could ask for vm->getNextWakeup()
tick which might be zero some day.
(d) getNextWakeup() might be now() or near now()  and sleeping might
be a bad idea
(e) getNextWakeup() might be now() or in the near past yet we might
get called another 8 times before the smalltalk process lurch awake
(no idea why that is observed).
(f)  Anyway you have some reflect of sleep time once you decide how
large that value has to be.
(g) Isn't it one CPU one process why sleep?
(h) The pthread_cond_timedwait (yes I did that years back) won't fly
because you miss the interrupt from socket/files/UI which leaves to
the odd behavior if squeak is busy good web server, if squeak is idle
the bad web server...   "it always sends at 50 packets per second "

Therefore to sleep you have to use some OS call that let's you sleep
but wake up early when work needs to be done.
So to help befuddle your operating systems come with a variety of
system calls that actually might or might not work.
Off then to consider aioSleep() which does this dance with aioPoll ()
which *cough* has different behaviour if or if there is any file
descriptors open. Oddly an iphone app might not have any open for your
image lacking changeset and no sockets open...

Anyway nanosleep is used as that promises to be more accurate. Then if
it terminates early (don't bother checking) we run the aioPoll.
If of course nanosleep is defective or non-existant, then we ask
aioPoll to do the wait, but that usually has even worse behaviour.
Anyway after nanosleep wakes do the dance and service those sockets
and file descriptors.


On Fri, Jul 15, 2011 at 10:15 AM, John M McIntosh
<[hidden email]> wrote:

> I'll see if can gather some historical thoughts on this later today
>
> Sent from my iPhone
>
> On 2011-07-15, at 7:47 AM, Juan Vuletich <[hidden email]> wrote:
>
>>
>> Bert Freudenberg wrote:
>>> On 15.07.2011, at 01:40, Matthew Fulmer wrote:
>>>
>>>
>>>> On my unix vm, Delay wakeups often happen a lot later than requested
>>>> if the idle process kicks in. Craig provided a bit of code from spoon
>>>> that fixes this issue:
>>>> http://bugs.squeak.org/view.php?id=7652
>>>>
>>>
>>> Very interesting.
>>>
>>> On John's 4.x Mac VM I get 990 wakeups/sec.
>>>
>>> Same for John's 5.7.4, 990/s.
>>>
>>> But 5.8, and recent Cog/Stack VMs only do < 500 wakeups/sec. Both Carbon and Cocoa versions.
>>>
>>> - Bert -
>>>
>>
>> Right. Strangely, on recent Mac VMs, the behavior is not affected by idle process / relinquish primitive. I turned Matthew's snippet into the attached test. Another strange thing is that (on a recent Mac VM) this test fails for 1mS and 5 mS, but passes for 2mS!
>>
>> HTH.
>>
>> Cheers,
>> Juan Vuletich
>> 'From Cuis 3.3 of 2 June 2011 [latest update: #1024] on 15 July 2011 at 8:28:03 am'!
>> !classDefinition: #RelinquishPrimitiveTest category: #'Kernel-Tests'!
>> TestCase subclass: #RelinquishPrimitiveTest
>>    instanceVariableNames: ''
>>    classVariableNames: ''
>>    poolDictionaries: ''
>>    category: 'Kernel-Tests'!
>>
>> !RelinquishPrimitiveTest methodsFor: 'testing' stamp: 'jmv 7/15/2011 08:25'!
>> testDelayAccuracy
>>    "
>>    RelinquishPrimitiveTest new testDelayAccuracy
>>    Test void relinquishPhysicalProcessor(void); in the VM.
>>    See http://bugs.squeak.org/view.php?id=7652
>>    See http://permalink.gmane.org/gmane.comp.lang.smalltalk.squeak.vm.devel/6381
>>    It appears that for some VMs, the relinquish primitiva takes too long to return?
>>
>>    This should print a number close to 1000
>>    | tally delay morph updateDelay |
>>    tally := 0. delay := Delay forMilliseconds: 1.
>>    updateDelay := Delay forMilliseconds: 1000.
>>    morph := StringMorph new openInWorld.
>>    [[tally := tally + 1. delay wait] repeat] forkAt: 44.
>>    [[morph contents: tally printString. tally := 0. updateDelay wait] repeat] forkAt: 45.
>>
>>    Evaluating this avoids the iddle process, and in some VMs (Linux) it seems to make the tally go from almost 500 to almost 1000.
>>    This trick doesn't seem to work on recent Mac VMs (the 4.2.4 Mac VM is always close 1000), as it is always a bit below 500
>>    [[] repeat] forkAt: 35
>>    "
>>    self testDelayAccuracy: 10.
>>    self testDelayAccuracy: 6.
>>    self testDelayAccuracy: 5.
>>    self testDelayAccuracy: 2.
>>    self testDelayAccuracy: 1! !
>>
>> !RelinquishPrimitiveTest methodsFor: 'testing' stamp: 'jmv 7/15/2011 08:27'!
>> testDelayAccuracy: delayTime
>>    "
>>    RelinquishPrimitiveTest new testDelayAccuracy
>>    See comment there.
>>    "
>>    | tally delay updateDelay counter |
>>    tally _ 0.
>>    delay _ Delay forMilliseconds: delayTime.
>>    updateDelay _ Delay forMilliseconds: 1000.
>>    counter _ [[tally _ tally + 1. delay wait] repeat] newProcess.
>>    counter resumeAt: 44.
>>    tally _ 0.
>>    updateDelay wait.
>>    counter terminate.
>>    self assert: tally > (900/delayTime) description: 'Delay accuracy. Observed: ',
>>        (1000.0 / tally roundTo: 0.01) printString, ' mS. Requested: ', delayTime asFloat printString, ' mS.'! !
>



--
===========================================================================
John M. McIntosh <[hidden email]>
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================
Reply | Threaded
Open this post in threaded view
|

Re: Delays should wakeup the idle process (patch)

ccrraaiigg
 

Hi John--

> The pthread_cond_timedwait (yes I did that years back) won't fly
> because you miss the interrupt from socket/files/UI which leaves to
> the odd behavior if squeak is busy good web server, if squeak is idle
> the bad web server...   "it always sends at 50 packets per second "

     In Spoon (the Flow plugin, really), when I signal an external
semaphore associated with a socket or whatever when activity happens, I
also signal the "activity" mutex that this pthread_cond_timedwait call
is waiting on. It works fine; in fact, I had to make this work well, to
wake up frequently for socket activity for remote messaging on headless
systems.

     At the time I wrote it, the Unix and Mac VMs remote messaging
performance was horrible over this very issue. I also experimented with
alternative calls, including select(), and nanosleep().
pthread_cond_timedwait() beat them handily. The aioPoll() stuff just
seems like a confusing mess.

     Also, having this as a named primitive in an external plugin has
been very convenient, for enabling this sort of experimentation without
having to restart the virtual machine.


-C

--
Craig Latta
www.netjam.org/resume
+31   6 2757 7177
+ 1 415  287 3547


Reply | Threaded
Open this post in threaded view
|

Re: Delays should wakeup the idle process (patch)

johnmci

Having ported Flow to OS-9 I can agree on all this.

Historical issues were

(a) pthread_cond_timedwait was a pthread_cond_timedwait_NP  meaning
platform specific, maybe that is no longer the case.
(b) select() was supported everywhere
(c) resistance to change
(d) Smalltalk socket implementation has to change (see (c))
(e) Heck I even wrote a translation later for Flow to old socket layer.

Maybe in this decade someone can take another run at it given the JIT
can way outrun the poor socket implementation.
On Sat, Jul 16, 2011 at 5:08 AM, Craig Latta <[hidden email]> wrote:

>
>
> Hi John--
>
>> The pthread_cond_timedwait (yes I did that years back) won't fly
>> because you miss the interrupt from socket/files/UI which leaves to
>> the odd behavior if squeak is busy good web server, if squeak is idle
>> the bad web server...   "it always sends at 50 packets per second "
>
>     In Spoon (the Flow plugin, really), when I signal an external
> semaphore associated with a socket or whatever when activity happens, I
> also signal the "activity" mutex that this pthread_cond_timedwait call
> is waiting on. It works fine; in fact, I had to make this work well, to
> wake up frequently for socket activity for remote messaging on headless
> systems.
>
>     At the time I wrote it, the Unix and Mac VMs remote messaging
> performance was horrible over this very issue. I also experimented with
> alternative calls, including select(), and nanosleep().
> pthread_cond_timedwait() beat them handily. The aioPoll() stuff just
> seems like a confusing mess.
>
>     Also, having this as a named primitive in an external plugin has
> been very convenient, for enabling this sort of experimentation without
> having to restart the virtual machine.
>
>
> -C
>
> --
> Craig Latta
> www.netjam.org/resume
> +31 6 2757 7177
> + 1 415 287 3547
>
>
>



--
===========================================================================
John M. McIntosh <[hidden email]>
Corporate Smalltalk Consulting Ltd.  http://www.smalltalkconsulting.com
===========================================================================
Reply | Threaded
Open this post in threaded view
|

Re: Delays should wakeup the idle process (patch)

Ted Wrinch
Hi John,

As the old maintainer of the Mac VM, I wondered if you might know anything about a performance issue I posted to the Seaside forum [1] below. In it I point out that the new Cog'ed Seaside and Pharo releases use 10% CPU at idle on the Mac.  

1) http://code.google.com/p/seaside/issues/detail?id=665&colspec=ID%20Type%20Status%20Priority%20Version%20Platform%20Owner%20Summary%20Milestone&start=100.

T.

Ted Wrinch