gen_tcp and message handling

Tony Rogvall tony@REDACTED
Thu Jan 6 22:01:23 CET 2005


2005-01-06 kl. 12.36 skrev Fredrik Thulin:

> On Thursday 06 January 2005 12.09, Tony Rogvall wrote:
>> 2005-01-06 kl. 11.15 skrev Fredrik Thulin:
>>> On Thursday 06 January 2005 04.36, James Hague wrote:
>>> ...
>>>
>>>> gen_tcp:connect?  The main reason I'm asking is that it would be
>>>> nice to register the Erlang port returned by gen_tcp:connect, then
>>>> send messages to that name, rather than having to pass the TCP
>>>> port number all around.
>>>
>>> It would be terribly easy for you to spawn a process that has a
>>> reference to the TCP socket, registers itself and turn signals you
>>> send it into gen_tcp:send().
>>
>> It is very easy, but slower !
>
> I trust you know better than me, but could you be a bit more elaborate
> as to why it is slower? I would guess it would only be marginally
> slower to do
>
>   Process -- signal --> registered process --> gen_tcp:send -> Socket
>

If you send messages asynchronously (cast) to the "registered process"  
and the
register process consume all input messages for each schedule you can
have reasonable throughput, but worse latency.

If you on the other hand use synchronous (call) for each send, you will  
for each
data message sent to the "socket" cause a reschedule while waiting for  
the
data to be sent to the socket.

Also the data will copied (not for shared heap) and will cause extra  
garbage collection.


> than to have Socket be a process itself that can be signalled, and have
>
>   Process -- signal --> Socket process
>

The Socket is a Port  (a handle to a linked in driver 'inet_drv') this  
means that
gen_tcp:send will eventually call erlang:port_command that is a  
somewhat expensive
call to a C function. This also means that there will not be an  
immediate reschedule
and that several gen_tcp:send can be issued without extra overhead.

BTW

You can actually do this (since Socket is a Port)

 > {ok, S} = gen_tcp:connect("www.google.com", 80, []).
 > S !  {self(), {command, "GET / HTTP/1.0\r\n\r\n"}}.
 > flush().

Shell got {inet_reply,#Port<0.40>,ok}
Shell got {tcp,#Port<0.40>,
                "HTTP/1.0 302 Found\r\nLocation:  
http://www.google.se/cxfer?c=PREF%3D:TM%3D1105045186: 
S%3DHo5ZD_3peVRdPb1c&prev=/\r\nSet-Cookie:  
PREF=ID=f6f0ef9be60f1f18:CR=1:TM=1105045186:LM=1105045186: 
S=itxWWs1uJdyfSCHJ; expires=Sun, 17-Jan-2038 19:14:07 GMT; path=/;  
domain=.google.com\r\nContent-Type: text/html\r\nServer:  
GWS/2.1\r\nContent-Length: 214\r\nDate: Thu, 06 Jan 2005 20:59:46  
GMT\r\nConnection: Keep-Alive\r\n\r\n<HTML><HEAD><TITLE>302  
Moved</TITLE></HEAD><BODY>\n<H1>302 Moved</H1>\nThe document has  
moved\n<A  
HREF=\"http://www.google.se/cxfer?c=PREF%3D:TM%3D1105045186: 
S%3DHo5ZD_3peVRdPb1c&prev=/\">here</A>.\r\n</BODY></HTML>\r\n"}
Shell got {tcp_closed,#Port<0.40>}
-------

Notice that you have to take care of the (low level) {inet_reply, S,  
Reply}
(a socket write may actually fail !)

/Tony




> but maybe I'm missing something. Maybe gen_tcp:send() is actually a
> signal to a process already. Then I would agree with you that it would
> actually make a difference. I have to read the source ;)
>
> /Fredrik




More information about the erlang-questions mailing list