Sendfile in erlang

Miguel Barreiro enano@REDACTED
Mon Nov 17 13:55:31 CET 2003


> Could you please post your benchmark programs too? I'm curious to try

My original test case was a bit buried inside much larger code - I guess a
simpler test case like this will be best suited so anyone can try it.
Just create a large enough file, create listeners on the receiving end and
start a network performance monitoring tool. I suggest netcat to receive
the streams ("nc -v -l -p 10000 >/dev/null" from the unix shell to listen
on port 10000 and send received data to the bit bucket), and nload ("nload
-t 1000 -o 500000 -i 500000") to display a nice ASCII graph - for those
not openview-oriented, that is :-)

> the unoptimised version in Oprofile (best program of the year) and see
> what kills the performance - user/kernel copies, context switches,
> erlang GC, select(), etc. If I remember correctly, Per Bergqvist was
> sending 10Mbps through Erlang on Celerons with only a fraction of the
> CPU with the kpoll'ified emulator.

Kpoll is something I want to test, too.
BTW, I'm pretty amazed by Oprofile. Great hint.

Regards,

Miguel
-------------- next part --------------
-module(sftest).
-author('enano@REDACTED').
-compile(export_all).


-define(BLOCK,4096).
-define(NUMBLOCKS,65536).


% Usage: create a large file (at least 2*?BLOCK*?NUMBLOCKS), create a few
% listeners on the receiving end (say, nc -l -v -p 10000 >/dev/null), launch
% a network performance monitor. Try nload -t 1000 for a nice ASCII graph.

% start(File_to_send, Dest_host, Base_dest_port, Number_of_concurrent_senders)
start() ->
    start("bigfile","matrix5",10000,4).

start(File,Host,BasePort,0) ->
	ok;
start(File,Host,BasePort,Num) ->
	spawn(?MODULE,task,[File,Host,BasePort+Num-1]),
	start(File,Host,BasePort,Num-1).

task(Filename,Host,Port) ->
    io:format("~n~p -> ~p:~p",[Filename,Host,Port]),
    {ok,File}=file:open(Filename,[read,raw]),
    {ok,Sock}=gen_tcp:connect(Host,Port,[binary,{packet,0}]),

    {Time,_}=timer:tc(?MODULE,loop_send,[File,Sock,?NUMBLOCKS]),
    io:format("~nloop_send: ~p usecs~n",[Time]),

    {ok,SockFD}=prim_inet:getfd(Sock),
    {Time2,_}=timer:tc(?MODULE,loop_sendfile,[File,SockFD,?NUMBLOCKS]),
    io:format("~nloop_sendfile: ~p usecs~n",[Time2]),
    receive after 2000 -> ok end.

% loop_send(From_descriptor, To_descriptor, Number_of_iterations)
loop_send(From,To,0) ->
    ok;
loop_send(From,To,Iters) ->
    {ok,Bin}=file:read(From,?BLOCK),
    gen_tcp:send(To,Bin),
    loop_send(From,To,Iters-1).

% loop_sendfile(From_descriptor, To_descriptor, Number_of_iterations)
loop_sendfile(From,To,Iters) ->
    loop_sendfile(From,To,0,Iters).
loop_sendfile(_,_,_,0) ->
    ok;
loop_sendfile(From,To,Pos,Iters) ->
    do_sendfile(From,To,Pos,?BLOCK),
    loop_sendfile(From,To,Pos+?BLOCK,Iters-1).
    
do_sendfile(From,To,Pos,Block) ->
    {ok,Sent}=file:sendfile(From,To,Pos,Block),
    if
	Sent==Block ->
	    ok;
	true  -> do_sendfile(From,To,Pos+Sent,Block-Sent)
    end.


More information about the erlang-questions mailing list