[erlang-questions] SSL performance

SeanD seand-erlang@REDACTED
Wed Feb 11 18:58:48 CET 2015

Thanks all,

There have been a number of useful suggestions here around improving the
test that I was carrying out.  I've modified the code so that it uses
{active,true} and can receive multiple chunks of data instead of one main
chunk.  I've also run the client and server on different machines and am
seeing the difference in performance between gen_tcp and ssl decrease.

It is now taking around 2 seconds to transfer 200MB of data using gen_tcp
and taking around 10 seconds to transfer the same data using SSL.  A few
people had concerns about the way I was measuring the time taken, but I
believe this should be ok as I only start measuring time after the initial
connection has been established.

Performance improves marginally if I send it in smaller chunks and the
relationship between time taken and size of data seems linear too.

The code enclosed was to demonstrate the difference in speed between
gen_tcp and ssl and the updated results mirror the performance change I see
in our own application when accessing data from a HTTPS server.  (I have no
control over the security mechanisms exposed by this server)

For reference, my updated code is shown below.




client() ->
    SomeHostInNet = "",
    {ok, Sock} = gen_tcp:connect(SomeHostInNet, 5678,
        [binary, {packet, 0}, {active, true}]),
    Before = erlang:now(),
    ok = do_client_recv(Sock),
    After = erlang:now(),
    ok = gen_tcp:close(Sock),
    io:format("Time taken: ~p microsecs~n",[total_microsecs(After) -

server(Data) ->

server(Data, NoOfIterations) ->
    {ok, LSock} = gen_tcp:listen(5678, [binary, {packet, raw}, {active,
    {ok, Sock} = gen_tcp:accept(LSock),
    send_tcp_data(Sock, Data, NoOfIterations),

ssl_client() ->
    SomeHostInNet = "",
    {ok, Sock} = ssl:connect(SomeHostInNet, 5679,
        [binary, {packet, raw}, {active, true}]),
    ok = ssl:ssl_accept(Sock),
    Before = erlang:now(),
    ok = do_client_recv(Sock),
    After = erlang:now(),
    ok = ssl:close(Sock),
    io:format("Time taken: ~p microsecs~n",[total_microsecs(After) -

ssl_server(Data) ->
    ssl_server(Data, 1).

ssl_server(_Data, 0) ->
ssl_server(Data, NoOfIterations) ->
    {ok, LSock} = ssl:listen(5679, [binary, {packet, raw},
    {ok, Sock} = ssl:transport_accept(LSock),
    ok  = ssl:ssl_accept(Sock),
    send_ssl_data(Sock, Data, NoOfIterations),

send_tcp_data(_Sock, _Data, 0) ->
send_tcp_data(Sock, Data, NoOfIterations) ->
    gen_tcp:send(Sock, Data),
    send_tcp_data(Sock, Data, NoOfIterations - 1).

send_ssl_data(_Sock, _Data, 0) ->
send_ssl_data(Sock, Data, NoOfIterations) ->
    ssl:send(Sock, Data),
    send_ssl_data(Sock, Data, NoOfIterations - 1).

total_microsecs({MegaSecs,Secs,MicroSecs}) ->
    (MegaSecs*1000000 + Secs)*1000000 + MicroSecs.

do_client_recv(Socket) ->
    do_client_recv(Socket, 0).

do_client_recv(Socket, Acc) ->
        {tcp, Socket, Data} ->
            do_client_recv(Socket, Acc + byte_size(Data));
        {ssl, Socket, Data} ->
            do_client_recv(Socket, Acc + byte_size(Data));
        {tcp_closed, Socket} ->
            io:format("Socket closed after transferring ~p bytes of
        {ssl_closed, _Socket} ->
            io:format("Socket closed after transferring ~p bytes of
        {tcp_error, Socket, Reason} ->
            io:format("Error: ~p~n",[Reason]);
        {ssl_error, Socket, Reason} ->
            io:format("Error: ~p~n",[Reason]);
        Else ->
            io:format("Unexpected result: ~p~n",[Else])
    after 20000 ->
            io:format("Receive timed out~n",[])
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20150211/a170c027/attachment.htm>

More information about the erlang-questions mailing list