[erlang-questions] why is gen_tcp:send slow?

Edwin Fine <>
Thu Jun 19 19:39:47 CEST 2008


How large is each packet? Can multiple packets fit into one TCP window? Have
you looked at the TCP/IP wire-level data with Wireshark/Ethereal to see if
the packets are being combined at the TCP level? If you see that you are
only getting one packet per TCP frame (assuming a packet is much smaller
than the window size), you might be falling foul of the Nagle congestion
algorithm. The fact that manually buffering your packets improves
performance suggests this may be the case. Nagle says that send, send, send
is OK, receive, receive, receive is ok, and even send, receive, send,
receive is ok, but you get into trouble if sends and receives are mixed
asymmetrically on the same socket (e.g. send, send, receive).

Also, I don't understand your transmit_loop. Where is it looping (or am I
misunderstanding something)?

>From what I have seen, people writing Erlang TCP/IP code do an {active,
once} receive, and when getting the first packet, drop into another loop
that does a passive receive until there's no data waiting, then go back into
the {active, once} receive. Are you doing this? I am not sure, but I fear
that if all your receives are {active, once} it will incur more CPU overhead
than the active/passive split. It's hard to know because I can't see enough
of your code to know what you are doing overall. Disclaimer: I'm no Erlang
or TCP/IP expert.

Hope this helps.

2008/6/19 Rapsey <>:

> I have a streaming server written in Erlang. When it was pushing 200-300
> mb/s the CPU was getting completely hammered. I traced the problem to
> gen_tcp:send.
> So instead of sending every audio/video packet with a single gen_tcp:send
> call, I buffer 3 packets and then send them all at once. CPU consumption
> dropped dramatically.
> On one of the servers I have a simple proxy, the main process that sends
> packets between the client and some other server looks like this:
>
> transmit_loop({tcp, Sock, Data}, P) when P#transdat.client == Sock ->
>     gen_tcp:send(P#transdat.server, Data),
>     inet:setopts(P#transdat.client, [{active, once}]),
>     {ok, P};
> transmit_loop({tcp, Sock, Data}, P) when P#transdat.server == Sock ->
>     gen_tcp:send(P#transdat.client, Data),
>     inet:setopts(P#transdat.server, [{active, once}]),
>     {ok, P};
> transmit_loop({start, ServerPort}, P) ->
>     {ok, Sock} = gen_tcp:connect("127.0.0.1", ServerPort, [binary,
> {active, once}, {packet, 0}]),
>     {ok, P#transdat{server = Sock}};
> transmit_loop({tcp_closed, _}, _) ->
>     exit(stop).
>
> The proxy is eating more CPU time than the streaming server.
> Is this normal behavior? The server is running  OSX 10.4
>
>
> Sergej
>
> _______________________________________________
> erlang-questions mailing list
> 
> http://www.erlang.org/mailman/listinfo/erlang-questions
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20080619/7bd8f209/attachment.html>


More information about the erlang-questions mailing list