[erlang-questions] gen_tcp nonblocking send
Fri May 2 20:03:57 CEST 2008
"When there is no choice, there is no management".
Assuming that not every problem is the same, there is always some merit in
being able to do things differently -- I, for one, like to have a choice
when deciding about how to do things.
As for complexity and weather or not is worth it, well, I suppose that would
depend on a problem one tries to solve. Easier and simple is usually good
but not always better - sometimes an extra effort may help in a long run.
Sometimes the fact that you did not manage to send the whole buffer may be
information in its own right (and, by definition, prompt you to do something
about it). Thus, you may choose to raise a performance related alarm/event,
or decide to start using additional communication channels, etc. And yes,
you may achieve all of it by blocking, and then timing out, and then do
something about it, and yes, that might be the best approach in 99% of
situations (*). But there is always a time when it doesn't, hence, the
question than would be, is a workaround worth it or not?
(*) Think of situations where both peers are using a single process (each)
for reading and writing to a socket, and potential for a deadlock caused by
exhaustion of both buffers - I saw this happening when multiple processes
are sharing a connection (via relay) during heavy traffic loads. Being able
to timely service receive instead of blocking on send will most certainly
prevent such a situation.
----- Original Message -----
From: "Per Hedeland" <>
Cc: <>; <>
Sent: Friday, May 02, 2008 1:26 PM
Subject: Re: [erlang-questions] gen_tcp nonblocking send
> "Valentin Micic" <> wrote:
>>You're right -- I did not read it carefully enough. Your suggestion would
>>not develop a scheduling problem. However, after reading it again, I'm
>>really not sure why would O_NDEALY be such an evil thing, if it is
>>implemented as a separate function call (and not as a flag), that would
>>return a binary containing unsent octets.
> But what's the point of giving that back to the application, when the
> only thing the application can do with it is to keep it around until
> gen_tcp says "OK, I can take some more" (an async message that the app
> has to "actively" receive) - at which point the application gives it
> back to gen_tcp, who may *still* not be able to send it all, and gives a
> new binary back, which the application has to keep around until... Seems
> to me like requiring quite a bit of complex programming for no gain.
>> It would certainly help (in this
>>case not-so) intelligent queuing on the caller side -- unlike your sender
>>that needs to do pre-emptive queuing, until it receive's ack from "relay",
>>it would need to queue only unsent octets, right?
> Yes, there is of course some possibility that new messages may arrive to
> sender before the ack after a gen_tcp:send() that didn't "really" block
> arrives. A "good" solution to that would be to (instead of the "relay"
> process) have an option that made gen_tcp:send() say "this will take a
> while, I'll send you a message when I'm done" instead of blocking, but
> *only* in the case where it would otherwise block (as opposed to what I
> called "async send", which does it always), without passing the unsent
> octets back.
> But again, is it worth the added complexity? Now you have a
> multiple-choice sender, and to fully test it you *must* produce the
> blocking scenario, whereas the simple async-send -> ack scheme always
> works the same, and only requires the code that you need for the "really
> blocking" case anyway. Of course there are cases where you have to deal
> with complexity to get the performance you need, but then a) you should
> first make sure that this really is one of those, and b) the next step
> would be to get rid of the "relay" process and have gen_tcp provide the
> simple async-send -> ack interface directly (after all, the relay
> process is just undoing what prim_inet does).
More information about the erlang-questions