[erlang-questions] RE: TCP performance

Dmitry Belyaev rumata-estor@REDACTED
Fri Jun 18 14:13:41 CEST 2010


accept/2 is not tail recursive, so it accepts only one connection.

accept(Server, LSock) ->
     case gen_tcp:accept(LSock) of
         {ok, Socket} ->
             gen_server:cast(Server, {accepted, self()}),
             gen_server:cast(gateway_verifier, {connected, Socket}),
             accept(Server, LSock);                       %%<-------------
         {error, closed} ->
             gen_server:cast(Server, {closed, self()})
     end


Dmitry Belyaev


On 06/18/2010 05:56 AM, Chris Hicks wrote:
>
> I'm under the impression that hotmail and the erlang mailing list do not get along. I'll try to reformat the previous message one more time in a different way and if it doesn't work I guess I'm just going to have to open a second account elsewhere simply for the mailing list...
>
> Second attempt:
>
> In designing the TCP server, which will handle all communication, for my project I based my design off of a couple of different tutorials, modified to suit my own needs. What I have is a gen_server that spawns a new process which waits for a connection on the single port of communication, when a connection is accepted this process tells the gen_server that it needs to spawn a new process and then it sends the socket off to another gen_server where the data will be grabbed and processed.
>
> As far as I understand it once the socket connection has been accepted there should be no reason why another connection can't be established on that port immediately following. In other words the system doesn't care if the data has been received or not, when it comes to allowing another connection to take place, only that the first connection has been made. Is that true?
>
> I ask because I ran a very simple test against the server which simply asked for a connection and then immediately closed it. Everything seems to work flawlessly except that making 1000 connections takes about 3.5 seconds and for my purposes that is a bit too long. The code for the server is below, and hopefully with a tip someone gave me earlier it will be formatted correctly:
>
>
> init(_Args) ->
>      process_flag(trap_exit, true),
>          case gen_tcp:listen(54637, [binary, {packet, 0}, {reuseaddr, true}]) of
>              {ok, LSock} ->
>                  State = #state{lsock = LSock},
>                  {ok, accept(State)};
>              {error, Reason} ->
>                  {stop, Reason}
>          end.
>
>
> accept(State = #state{lsock=LSock}) ->
>      proc_lib:spawn(?MODULE, accept, [self(), LSock]),
>      State.
>
>
> accept(Server, LSock) ->
>      case gen_tcp:accept(LSock) of
>          {ok, Socket} ->
>              gen_server:cast(Server, {accepted, self()}),
>              gen_server:cast(gateway_verifier, {connected, Socket});
>          {error, closed} ->
>              gen_server:cast(Server, {closed, self()})
>      end.
>
>
> This is the handle_cast callback for the gateway_verifier gen_server:
>
>
>
> handle_cast(Request, State) ->
>      case Request of
>          {connected, Socket} ->
>              {noreply, recv({State, Socket})};
>          {'EXIT', _From, _Reason} ->
>              {noreply, State};
>          _Other ->
>              {noreply, State}
>      end.
>
>
> And these are the functions which will start the processing of the data sent along the socket:
>
>
> recv({State, Socket}) ->
>      proc_lib:spawn(?MODULE, recv, [self(), Socket]),
>      State.
>
>
> recv(_Server, Sock) ->
>      case gen_tcp:recv(Sock) of
>          {ok, _Packet} ->
>              %% Do some fancy stuff here
>              ok;
>          {error, Reason} ->               {stop, Reason}
>      end.
>
>
>
> This is my first real attempt at this so I wouldn't be surprised if there were some glaring inefficiencies in there. Any thoughts on how to increase the speed of accepting incoming connections?
> ----------------------------------------
>    
>> From: silent_vendetta@REDACTED
>> To: erlang-questions@REDACTED
>> Subject: TCP performance
>> Date: Thu, 17 Jun 2010 18:41:22 -0700
>>
>>
>> In designing the TCP server, which will handle all communication, for my project I based my design off of a couple of different tutorials, modified to suit my own needs. What I have is a gen_server that spawns a new process which waits for a connection on the single port of communication, when a connection is accepted this process tells the gen_server that it needs to spawn a new process and then it sends the socket off to another gen_server where the data will be grabbed and processed.
>> As far as I understand it once the socket connection has been accepted there should be no reason why another connection can't be established on that port immediately following. In other words the system doesn't care if the data has been received or not, when it comes to allowing another connection to take place, only that the first connection has been made. Is that true?
>> I ask because I ran a very simple test against the server which simply asked for a connection and then immediately closed it. Everything seems to work flawlessly except that making 1000 connections takes about 3.5 seconds and for my purposes that is a bit too long. The code for the server is below, and hopefully with a tip someone gave me earlier it will be formatted correctly:
>> init(_Args) ->     process_flag(trap_exit, true),    case gen_tcp:listen(54637, [binary, {packet, 0}, {reuseaddr, true}]) of        {ok, LSock} ->             State = #state{lsock = LSock},            {ok, accept(State)};        {error, Reason} ->             {stop, Reason} end. accept(State = #state{lsock=LSock}) ->     proc_lib:spawn(?MODULE, accept, [self(), LSock]),    State. accept(Server, LSock) ->     case gen_tcp:accept(LSock) of        {ok, Socket} ->             gen_server:cast(Server, {accepted, self()}),            gen_server:cast(gateway_verifier, {connected, Socket});        {error, closed} ->             gen_server:cast(Server, {closed, self()}) end.
>> This is the handle_cast callback for the gateway_verifier gen_server:
>> handle_cast(Request, State) ->     case Request of        {connected, Socket} ->             {noreply, recv({State, Socket})};         {'EXIT', _From, _Reason} ->             {noreply, State};        _Other ->             {noreply, State} end.
>> And these are the functions which will start the processing of the data sent along the socket:
>> recv({State, Socket}) ->     proc_lib:spawn(?MODULE, recv, [self(), Socket]), State. recv(_Server, Sock) ->     case gen_tcp:recv(Sock) of        {ok, _Packet} ->             %% Do some fancy stuff here            ok;        {error, Reason} ->             {stop, Reason} end.
>>
>>
>> This is my first real attempt at this so I wouldn't be surprised if there were some glaring inefficiencies in there. Any thoughts on how to increase the speed of accepting incoming connections?
>> _________________________________________________________________
>> Hotmail is redefining busy with tools for the New Busy. Get more from your inbox.
>> http://www.windowslive.com/campaign/thenewbusy?ocid=PID28326::T:WLMTAGL:ON:WL:en-US:WM_HMP:042010_2
>>      
>   		 	   		
> _________________________________________________________________
> Hotmail has tools for the New Busy. Search, chat and e-mail from your inbox.
> http://www.windowslive.com/campaign/thenewbusy?ocid=PID28326::T:WLMTAGL:ON:WL:en-US:WM_HMP:042010_1
> ________________________________________________________________
> erlang-questions (at) erlang.org mailing list.
> See http://www.erlang.org/faq.html
> To unsubscribe; mailto:erlang-questions-unsubscribe@REDACTED
>
>
>    


More information about the erlang-questions mailing list