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