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

Arun Muralidharan arun11299@REDACTED
Mon May 20 17:28:22 CEST 2013


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
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20130520/07601d98/attachment.htm>


More information about the erlang-questions mailing list