[Spread-users] Spread performance

Pete Emerson pete at theemersons.org
Wed Jul 2 19:29:58 EDT 2008


I've written a bare-bones file transfer using Spread 3.17.4 and the  
latest Perl module.

Everything works, but I'm wondering if my performance results are  
typical or if I might be missing something and can squeeze out more.

The sender is simple, and in my tests, it completes the sending in @4  
seconds for a 100MB file. The receiver is threaded (currently limited  
to 10 threads), and all it does is spit the messages into files and  
then send an md5sum (a separate program assembles the chunks and is  
outside my area of interest for this question). On the receiver end,  
all packets are sent to disk in @40 seconds (2.5MB/s). This is on a  
single box that's virtualized to 4 machines, 1 sender, 3 receivers, so  
the network latency should be optimal. I've played with packet size  
(up to 100KB / packet), the usleep time between sending packets, and  
the number of threads, with varying results. I've also changed the  
type of message (I even made it UNRELIABLE_MESS), with little change  
in results. When I use scp for comparison's sake, I'm getting over 47  
MB/s.

Now, I don't expect to deliver my files at 47 MB/s, despite the  
packets not being encrypted as in scp, but I'm not yet convinced that  
I shouldn't be able to do better than 2.5 MB/s. My question is this:  
is my bottleneck something inherent to Spread, or is my code simply  
deficient and I've missed something obvious? If I can't improve the  
speed, then what I'm looking at is needing @19 nodes (with no slowdown  
via the spread/multicast method!) before an iterative scp is slower.   
Any tips and comments would be appreciated, including moving to  
POE::Component::SpreadClient to get rid of the threads, although I am  
not POE fluent.

Here's the core of the sender:

open INFILE, $file or die "Can't read $file: $!\n";
while (($n = read INFILE, $data, $size) != 0) {
       $i++;
       Spread::multicast($mbox, UNRELIABLE_MESS, 'chat1', 1, "$i| 
$data");
       usleep(250);
}

and the core of the receiver (the handler sub simply takes the data  
and shoves it to disk and marks the thread as joinable):

while (1) {
       my @arr = Spread::receive($mbox);
       while (keys %done >= $max_threads) {
               foreach my $id (keys %threads) {
                       if ($done{$id}) {
                               $threads{$id}->join();
                               delete $done{$id};
                               delete $threads{$id};
                       }
               }
       }
       $thread_id++;
       $done{$thread_id} = 0;
       $threads{$thread_id} = threads->create(\&handler, $mbox,  
$thread_id, @arr);
}

Thanks,
Pete




More information about the Spread-users mailing list