[erlang-questions] Inter-node communication bottleneck

Jihyun Yu yjh0502@REDACTED
Mon Sep 8 14:12:39 CEST 2014


Hi,

I couldn't spend much time after last update. It seems that using
multiple TCP sockets is not that scalable as well. I ran a test with
following configurations.

 - 12 cores, 24 threads server (Intel L5640 x 2)
 - Two Erlang VM on two docker containers
 - Connects with 12 TCP connections and send/recv packets
 - [{delay_send,true}, {high_watermark,1024000}]

With single integer term, total bandwidth is capped on about ~10MB/s.
With single binary term <<"hello">>, total bandwidth is capped on about
20~30MB/s. Two Erlang VM consume almost all CPU resources (2400% total),
so bandwidth per CPU usage is much worse than Erlang messaging case. I
didn't run perf yet, so I don't know where is an bottleneck.

I attached test source code so you can reproduce the result. Please tell
me if there is an error on configurations/test codes/...


[1] http://www.erlang.org/doc/man/inet.html

On Mon, Sep 08, 2014 at 03:59:04AM -0700, Dror Mein wrote:
> I encountered the same problem. any updates or new successes? the binary_to_term over tcp sounds promising.
-------------- next part --------------
-module(test_tcp).

-export([run_tcp/3, recv_tcp/3, send_tcp/4]).

-define(SOCKET_OPTS, [{active, false}, binary, {packet, 4}]).

run_tcp(Port, P, N) ->
    spawn_link(fun() ->
        recv_tcp(Port, P, N)
    end),
    send_tcp(localhost, 10000, P, N).

recv_tcp(Port, P, N) ->
    {ok, ListenSocket} = gen_tcp:listen(Port, ?SOCKET_OPTS),
    lists:foreach(fun(Idx) ->
        {ok, Socket} = gen_tcp:accept(ListenSocket),
        spawn_monitor(fun() ->
            io:format("receiving ~p/~p~n", [Idx, P]),
            recv_n(Socket, N),
            io:format("receiving ~p/~p done~n", [Idx, P]),
            ok = gen_tcp:close(Socket)
        end)
    end, lists:seq(1, P)),
    waitdown(P),
    io:format("closing listen socket~n"),
    ok = gen_tcp:close(ListenSocket).

recv_n(_Socket, 0) -> ok;
recv_n(Socket, N) ->
    {ok, _Data} = gen_tcp:recv(Socket, 0),
    recv_n(Socket, N-1).

send_tcp(Host, Port, P, N) ->
    lists:foreach(fun(Idx) ->
        spawn_monitor(fun() ->
            {ok, Socket} = gen_tcp:connect(Host, Port, ?SOCKET_OPTS),
            io:format("sending ~p/~p~n", [Idx, P]),
            send_n(Socket, N),
            io:format("sending ~p/~p done~n", [Idx, P]),
            ok = gen_tcp:close(Socket)
        end)
    end, lists:seq(1, P)),
    waitdown(P).

send_n(_, 0) -> ok;
send_n(Socket, N) ->
    gen_tcp:send(Socket, term_to_binary(N)),
    send_n(Socket, N-1).

waitdown(0) -> ok;
waitdown(Count) ->
    receive
        {'DOWN', _, process, _, normal} ->
            waitdown(Count-1)
    end.


More information about the erlang-questions mailing list