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

聂安 nieanan3602@REDACTED
Mon May 20 16:30:09 CEST 2013


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 packages 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)
 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}=State) ->
 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                       {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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20130520/a74bf96f/attachment.htm>


More information about the erlang-questions mailing list