[erlang-questions] Re: Need parallel calls to gen_server:call, similar but different to gen_server:multi_call

Joe Armstrong <>
Thu Oct 1 10:09:23 CEST 2009


On Thu, Oct 1, 2009 at 3:36 AM, Robert Virding <> wrote:
> The problem is getting the right message formats for gen_server, and they
> aren't really specified. One alternative would be to use gen_server:cast to
> send and then handle the replies explicitly yourself.
>
> Robert
>
> P.S. One long, never-resolved discussion Joe and I had for many years was
> whether you should have an API like is done in gen_XXX or to explicitly
> specify the message protocol. Having the message protocol would allow you to
> increase concurrency.

Even worse - I'm pretty sure the entire system is "over synchronized" - we made
many interactions into "pure RPC" in order to avoid buffer overrun
problems. ie if
we have a producer and consumer, we have to make sure that the
consumer runs faster than the producer - we solved this by explicitly
syncing the producer and consumer.
we write code like this all the time:

         rpc(Pid, X) ->
               Pid ! {self(), X},
               receive
                     {Pid, Reply} ->
                            Reply
              end.


The problem is that the client blocks until it receives a reply from
the server. So there is
no concurrency, either the client runs or the server. No problem in
1986 on a unicore, but
today we could do better.

We *do* need to sync up producers and consumers, because we can never know if
a producer produces stuff faster than the consumer can consume it.

There are a couple of ways to do this - in Erlang code we could
require the sever to ack
every (say) 10'th command - so a client could pump out ten requests
before suspending and
checking that the server was keeping up, this would increase
concurrency since it's not
necessary to sync up every RPC.

Another idea might be to use something like TCP "backpressure" between
erlang processes
viewing causing a client to suspend if the inbox of a server was
getting large - but this would
introduce an entire class of new problems and create strange inter-dependencies.

We should also probably have some abstractions for concurrent pipes.

<aside>setting up pipes in unix (example find ... | sort | uniq | wc)
is favorite example of how easy it is to write a parallel program :-)
</aside>


    pipe([F1, F2, F3, ..., Fn])

in which spawn(F1)  starts a process which sends messages to a process
started by
spawn(F2) ... which are consumed by a process that is started by spawn(F3)

The trick would be to handle the queue sizes between the steps in the pipeline
and deal with out of band data and exceptions.

A naive implementation of pipe is easy but to avoid buffer overruns
would be inefficient.
(consider the case where F1 produces messages extremely quickly, but
F2 is very slow :-)

/Joe

>
> 2009/10/1 Mihai Balea <>
>
>>
>>
>> On Sep 30, 2009, at 7:33 PM, Steve Davis wrote:
>>
>>  ...and the following is not appropriate to your needs?
>>>
>>> Responses = [gen_server:call(Pid,Request) || Pid <- PidList]
>>>
>>
>> That would serialize the calls to the gen_server processes, not taking
>> advantage of the parallel nature of erlang
>> How about using rpc:pmap or rpc:parallel_eval?
>>
>> Mihai
>>
>> ________________________________________________________________
>> erlang-questions mailing list. See http://www.erlang.org/faq.html
>> erlang-questions (at) erlang.org
>>
>>
>


More information about the erlang-questions mailing list