[erlang-questions] erlang socket send and rcv, high CPU usage

Paul Peregud paulperegud@REDACTED
Mon May 20 17:36:11 CEST 2013


Please also remember that debug printing costs a lot more then sending
a packet via socket. If you want to measure you need to make sure that
you don't print a message per packet.

And for really big values of throughput you need to use {active,
false} with gen_tcp:recv.

Search information on erlyvideo and etorrent. Both have reached very
nice values of thoughput.

On Mon, May 20, 2013 at 5:28 PM, Arun Muralidharan <arun11299@REDACTED> wrote:
> Hello Niean,
> Mentioned below are few of my suggestions:
> 1) Disable Nagle in server.
> 2) Try to use {active, once} in server. {active, true} setting may overflow
> your TCP buffer. In between, how much have you set the TCP read-write buffer
> (both in OS and application)?
> 3) Not sure what you are trying to achieve with port_command. Its not clear
> to me..
>
> Other design related suggestions would be to:
> 1) Use async communication model using prim_inets as the listener.
> 2) Better to use an FSM for managing socket states and flow control.
>
> Thanks,
> Arun
>
> -Arun
>
>
> On Mon, May 20, 2013 at 8:00 PM, 聂安 <nieanan3602@REDACTED> wrote:
>>
>> hi all,
>> I have a question about the high cpu usage when sending and receiving data
>> via erlang-socket.
>> My program uses a C/S mode. First, the server start a listening socket,
>> and then the client connect to the server by using gen_tcp:connect. When
>> establishing a connection, the client will keep sending "info" package to
>> the server while waiting for a response from the client ; the server  will
>> respond an "info_ack" to the client when receiving a "info" package.  When
>> there's one client, at most 20000 packages per second are sent betweent C/S,
>> while cpu usage reaches about 90%. My package is very little, at most
>> 10Bytes, so my netcard is idle. When doing the same thing by C language, the
>> cpu usage is just 6% while my netcard turns busy with about 500000 packa ges
>> per second.
>> I have no idea why erlang gets so cpu-consuming.  My program goes as
>> follows:
>>
>> Server
>> config items about socket setting:
>> {tcp_listen_opts,
>> [binary,{packet,0},{reuseaddr,true},{exit_on_close,true},{active,false}]}
>>
>>  30 start_connection(Parent, Sock, SockTransform) ->
>>  31     process_flag(trap_exit, true),
>>  32     Name =
>>  33     case catch ?NET:connection_string(Sock, inbound) of
>>  34     {ok, Str}        -> Str;
>>  35     {error, enotcon} -> ?NET:fast_close(Sock),exit(normal);
>>  36     {error, _Reason} -> ?NET:fast_clost(Sock),exit(normal)
>>  37     end,
>>  38     Msg = io_lib:format("accept connection ~p(~p)", [Name, self()]),
>>  39     ?DEBUG(Msg), log:log(notice, ?MODULE, Msg),
>>  40     ClientSock = socket_op(Sock, SockTransform),
>>  41     ClientSock = Sock,
>>  42     {PHost, PPort, Host, Port} =
>>  43         socket_op(Sock, fun(S)->?NET:socket_ends(S,inbound) end),
>>  44     State = #state{
>>  45         parent          = Parent,
>>  46         sock            = ClientSock,
>>  47         name            = list_to_binary(Name),
>>  48         callback        = undefined,
>>  49         host            = Host,
>>  50         port            = Port,
>>  51         peer_host       = PHost,
>>  52         peer_port       = PPort
>>  53     },
>>  54     try
>>  55         %ok = inet_op(),
>>  56         inet:setopts(ClientSock, [{active, true}]),
>>  57         Ret = rcv_loop(State),
>>  58         WMsg=lists:flatten(io_lib:format("closing connection ~p(~p), "
>>  59             "reason: ~p", [Name,self(),Ret])),
>>  60         ?DEBUG(WMsg), log:log(warning, ?MODULE, WMsg)
>> &nbs p;61     catch
>>  62     E:R ->
>>  63         EMsg=lists:flatten(io_lib:format("closing connection ~p(~p), "
>>  64             "reason: ~p:~p", [Name, self(), E, R])),
>>  65         ?DEBUG(EMsg), log:log(error, ?MODULE, EMsg)
>>  66     after
>>  66     after
>>  67         ?NET:fast_close(ClientSock),
>>  68         Msg2=lists:flatten(io_lib:format("connection ~p(~p) closed",
>>  69             [Name, self()])),
>>  70         ?DEBUG(Msg2), log:log(notice, ?MODULE, Msg2)
>>  71     end,
>>  72     normal.
>>  73
>>  74 rcv_loop(#state{sock=Sock}=Sta te) ->
>>  75     receive
>>  76     {tcp, Sock, Binary} ->
>>  77         NState = report_run(State, Binary),% calls port_command to
>> send ack pkg
>>  78         %inet:setopts(Sock, [{active, once}]),
>>  79         rcv_loop(NState);
>>  80     {tcp_closed, Sock}  -> 'peer closed';
>>  81     _Other              -> rcv_loop(State)
>>  82     after ?RCV_TIMEOUT  -> 'rcv timeout'
>>  83     end.
>>
>>
>>
>> Client
>>  10 -define(TCP_OPTIONS, [binary, {packet,0}, {active, false},
>>  11                   &nb sp;   {exit_on_close,true}, {reuseaddr,true}]).
>> 101 setup_short_connection(Host, Port, #state{id=Id}=State) ->
>> 102     case gen_tcp:connect(Host, Port, ?TCP_OPTIONS) of
>> 103     {ok, Socket}    ->
>> 104         ?DEBUG("client(~p) connected to ~p:~p", [Id,Host,Port]),
>> 105         inet:setopts(Socket, [{active, once}]),
>> 106
>> send_request_and_wait_for_response(State#state{socket=Socket});
>> 107     {error, Reason} ->
>> 108         EMsg=lists:flatten(io_lib:format("client(~p) connect failed,"
>> 109             "reason: ~p", [Id, Reason])),
>> 110         ?DEBUG(EMsg),
>> 111         {error, 'connect failed'}
>> 112     end.
>> 118
>> send_request_and_wait_for_response(#state{id=Id,requ_cnt=RequCnt}=State) ->
>> 119     try
>> 120         Ref = RequCnt,
>> 121         NState  = send_request(State, Ref),
>> 122         wait_for_response(NState, Ref)
>> 123     catch
>> 124     E:R ->
>> 125         EMsg = io:format("client(~p) failed in
>> send_request_and_wait_for_response"
>> 126             ", reason: ~p:~p", [Id, E, R]),
>> 127         ?DEBUG(EMsg),
>> 128         {error, 'error during send or wait'}
>> 129     end.
>> 130
>> 131 send_request(#state{socket=Sock,requ_cnt=RequCnt}=State, Ref) ->
>> 132     Data = {{"business", "aos"}, {"ref", Ref}},
>> 133     Pkg  = {{"type", "key"}, {"data", Data}},
>> 134     JPkg = term_to_binary(Pkg),
>> 135     true = erlang:port_command(Sock, JPkg, [nosuspend]),
>> 136     State#state{requ_cnt=RequCnt-1}.
>> 137
>> 138 wait_for_response(#state{socket=Sock}=State, Ref) ->
>> 139     receive
>> 140     {tcp, Sock, Binary} ->
>> 141         ok = inet:setopts(Sock, [{active,once}]),
>> 142         case report_run(State, Binary, Ref) of
>> 143         {response, NState} ->
>> send_request_and_wait_for_response(NState);
>> 144         {other, _}         -> wait_for_response(State, Ref)
>> 145         end;
>> 146     _Other      -> wait_for_response(State, Ref)
>> 147     after 30000 -> {error, 'rcv response timeout'}
>> 148     end.
>>
>>
>> I'm sorry for my poor English. I will be very grateful if someone help me
>> to solve this problem.
>>
>> yours
>> niean
>>
>>
>>
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
>
>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>



-- 
Best regards,
Paul Peregud
+48602112091



More information about the erlang-questions mailing list