[squeak-dev] Problem with fork

Mariano Martinez Peck marianopeck at gmail.com
Thu Jul 2 14:34:31 UTC 2009


On Wed, Jul 1, 2009 at 5:40 PM, Eliot Miranda <eliot.miranda at gmail.com>wrote:

>
>
> On Wed, Jul 1, 2009 at 10:55 AM, Mariano Martinez Peck <
> marianopeck at gmail.com> wrote:
>
>>
>>
>> On Wed, Jul 1, 2009 at 3:10 PM, Eliot Miranda <eliot.miranda at gmail.com>wrote:
>>
>>> Hi Mariano,
>>>     Smalltalk's scheduler is preemptive across priorities and
>>> co-operative within priorities, which is a well-chosen real-time scheduling
>>> policy giving precise control over processes.  Because all your processes
>>> have the same priority they don't preempt the first process and so they
>>> don't get to run until after the doit has executed and the system has
>>> returned to some idle loop state.  If instead you change your code to either
>>> use a higher priority, e.g. [...] forkAt: Processor activePriority + 1, or
>>> to use yield, e.g. [....] fork. Processor yield, then you'll be able to get
>>> your desired behaviour.
>>>
>>
>> Eliot: Thanks for the reply. I think I am understanding a bit more. Let me
>> explain myself a bit more what I am actually trying to do. I have SqueakDBX
>> which uses FFI to call external functions of OpenDBX and do queries to
>> databases. If you use SqueakDBX in a webapplication, like seaside, you will
>> have like several forks using SqueakDBX. And that's exactly what I am trying
>> to simulate: multiples forks (in a webapp they would be users connected). I
>> am doing some benchmarks as I have some things to define (timeouts) and see
>> how they affect this situation.
>>
>> My real code (of the benchmark) is something like this:
>>
>> collect: aBlock
>>
>> |semaphores|
>> semaphores := Array new: self amountOfForks.
>> 1 to: self amountOfForks do: [ :index | semaphores at: index put:
>> Semaphore new ].
>>
>>     1 to: self amountOfForks do: [:i |
>>         [
>>         mutex critical: [ times add: (MessageTally time: aBlock) ].
>>         (semaphores at: i) signal.
>>         ] forkAt: self benchPriority
>>     ].
>>
>>     semaphores do: [:each | each wait ].
>>
>> In this case, aBlock is a piece of code that does a big select.
>>
>> During all the methods which are called in aBlock (SqueakDBX methods)
>> there are for example, FFI calls and several things more. Suppose all the
>> forks are with the same priority. My question is now when would the
>> scheduler take another one?  As OpenDBX supports Asynchronous queries I just
>> ask using FFI is the query if done or not and the function returns
>> immediately. But, in order to let another connection to do another query,
>> what I do, in case the query is not finished is:
>>
>> (Delay forMilliseconds: 1000) wait
>>
>> This piece of code will free that process and pass to another? if not, I
>> must add a yield ?
>>
>
> Yes it will pass to another and no you don't need a yield.  Internal to a
> delay there is a semaphore and when the program does aDelay wait the active
> process waits on that semaphore.  The scheduler then switches to the first
> highest priority process.  The Delay class maintains a process that uses a
> VM primitive primSignal:atMilliseconds: to start a timer in the VM that will
> signal the semaphore supplied to the primitive when the timer expires.  The
> class side process then wakes (preempting the current process if the delay
> process is of higher priority, which it very likely is), checks the set of
> waiting delays and signals the semaphores of those that should be woken up,
> which will make those processes runnable.
>
> You only need to do a yield when a process wants to allow a process at the
> same priority a chance to run but the yielding process has work to do.  If
> instead the process waits on a semaphore (in a Delay or explicitly) it will
> effectively yield.  Also note that the yield primitive is only a space
> efficient version of the following Smalltalk code:
>
>      oldSlowLetsCreateLotsOfObjectsButNotRequireVMModificationsYield
>         | sem |
>         sem := Semaphore new.
>         [sem signal] fork.
>         sem wait
>
> which is a real waste if there are no processes at the current priority
> level waiting to run, hence the VM primitive which avoids all this work by
> simply inspecting teh current priority level's runnable process queue.
>
> I was going to suggest that you read the class comments of
> ProcessorScheduler, Process, Semaphore, Mutex and Delay, but they're pretty
> simplistic.  Better to read the blue book chapters on the scheduler either
> here
> http://web.archive.org/web/20060615014524/http://users.ipa.net/~dwighth/smalltalk/bluebook/bluebook_chapter29.html#ControlPrimitives29<http://web.archive.org/web/20060615014524/http://users.ipa.net/%7Edwighth/smalltalk/bluebook/bluebook_chapter29.html#ControlPrimitives29> or
> here: http://stephane.ducasse.free.fr/FreeBooks/BlueBook/
>


Henrik:   thanks for your explanation!!

Eliot: IDEM. And thanks for the references!

Mariano



>
> I'm sure others will have better reference material to suggest.
>
> cheers
> e.
>
>
>>
>> Thanks a lot for the help!
>>
>> Mariano
>>
>>
>>
>>>
>>>
>>> On Wed, Jul 1, 2009 at 7:41 AM, Mariano Martinez Peck <
>>> marianopeck at gmail.com> wrote:
>>>
>>>> Hi folks! I am doing some benchmarks and I having problems with fork (I
>>>> think).
>>>>
>>>> I have this method collect:
>>>>
>>>> collect
>>>> |semaphores tr|
>>>> semaphores := Array new: 10.
>>>> tr := ThreadSafeTranscript new.
>>>> tr open.
>>>> 1 to: 10 do: [ :index | semaphores at: index put: Semaphore
>>>> forMutualExclusion ].
>>>>
>>>>     1 to: 10 do: [:i |
>>>>         [
>>>>         tr show: 'one fork'; cr.
>>>>         (semaphores at: i) signal.
>>>>         ] fork
>>>>     ].
>>>>
>>>>     semaphores do: [:each | each wait ].
>>>>     tr show: 'all forks proccesed'; cr.
>>>>
>>>>
>>>> What I want is that the method collect returns when ALL of the forks
>>>> created inside, are finished. Obviously in my real code, I don't do a
>>>> transcript show: but another thing.
>>>>
>>>> I would expect something like this:
>>>>
>>>> one fork
>>>> one fork
>>>> one fork
>>>> one fork
>>>> one fork
>>>> one fork
>>>> one fork
>>>> one fork
>>>> one fork
>>>> one fork
>>>> all forks proccesed
>>>>
>>>> But the output is:
>>>>
>>>>
>>>> all forks proccesed
>>>> one fork
>>>> one fork
>>>> one fork
>>>> one forkone fork
>>>> one fork
>>>> one fork
>>>> one forkone fork
>>>> one fork
>>>> one fork
>>>> one forkone fork
>>>>
>>>> So, I guess it isn't working :(   I don't know too much about forks so
>>>> any help is welcome!
>>>>
>>>> can be a problem with  ThreadSafeTranscript  ? If so, how could I test
>>>> if my code is working as expected ?
>>>>
>>>> Thanks,
>>>>
>>>> Mariano
>>>>
>>>>
>>>>
>>>>
>>>>
>>>
>>>
>>>
>>>
>>
>>
>>
>>
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20090702/194782bb/attachment.htm


More information about the Squeak-dev mailing list