slow read from spawned processes

Per Hedeland per@REDACTED
Mon Jul 26 02:11:22 CEST 1999

Bernd Roscher wrote:
>I've spawned two processes this way (C++ executables), one 
>is sending messages of length 54, the other receives the messages.
>The Erlang program behind this, provides a routing mechanism
>between several processes, thus connecting these two processes 
>in this example.
>The final program, that uses this routing facility, shall 
>call a non-blocking read inside an execution loop.
>But the blocking read (upto now the receiving process is able
>to block because it does not do anything else besides receiving
>the messages) appears to be 7-10 times faster then the nonblocking

Well, if you're asking why non-blocking reads in C++ programs are slow,
maybe this is the wrong place:-) - but perhaps there are some C++ gurus
around. In terms of Unix system calls (assuming this is on Unix), I'd
say that a non-blocking read is exactly as fast as a blocking one
reading the same amount of data. However if your program is actually
doing multiple reads, with only the final one actually retrieving any
data, this would of course mean that the entire process takes a longer
time - and system calls are generally "expensive" (perhaps some C++
library functions are doing this "under the covers", I wouldn't know).

You *might* get better results using select() or poll() if possible,
doing reads only when data is actually available - assuming you only do
a single read each time select/poll says it's OK, you don't need
non-blocking reads in this case. But again, if you end up doing multiple
"polling" select/poll calls before actually reading anything, it will
still cost you (this is actually a problem that the Erlang runtime
system suffers from too) - best is if you can arrange your program such
that its "main loop" is based on a *blocking* select/poll.

>Another problem is the Erlang interpreter. In the case of a slow 
>receiver it allocates a mass of memory (with 100000 messages sent it
>allocates about 50% of the whole systems memory which is 128MB Ram
>and raises upto 75% in subsequent runs). But the whole amount of data 
>sent is just 5.6 MB. 
>Where is the rest of the memory spent?

Impossible to say without knowing what your program does of course, but
in general there are two issues to consider:

- Your data might use up more space as Erlang terms than as "raw" data -
  e.g. I believe a list of bytes uses basically eight bytes per data
  byte. Using "binaries" (if you aren't already) may help with this,
  they're particularly suited for applications where you mostly pass
  un-interpreted chunks of data through.

- If your Erlang processes create a lot of data, their heaps may grow
  rapidly, and in "pathological" cases may not be garbage collected as
  quickly as you'd like - I could imagine that you might run into this
  with processes that do some work and then exit in normal cases, but
  may be hanging around waiting for an ack or whatever in your case of a
  "slow receiver".

Apropos, you should consider that Erlang message passing is (by design)
asynchronous and non-flow-controlled - if you send a lot of data and
risk having "slow receivers", you probably need to have some form of
end-to-end flow control to prevent message queues from growing without
bounds (i.e. you'd need to add this if it isn't implicit in your
application protocols).

--Per Hedeland

More information about the erlang-questions mailing list