I’m working on a project, implemented in Perl, and thought it would be an idea to use threads to distribute the work, because the tasks can be done independent of each other and only reading from shared data in memory. However, the performance is nowhere near as I expect it to be. So after some investigation I can only conclude that threads in Perl basically suck, but I keep wondering the performance goes down the drain as soon as I implement one single shared variable.
For example, this little program has nothing shared and consumes 75% of the CPU (as expected):
use threads;
sub fib {
my ( $n ) = @_;
if ( $n < 2 ) {
return $n;
} else {
return fib( $n - 1 ) + fib( $n - 2 );
}
}
my $thr1 = threads->create( 'fib', 35 );
my $thr2 = threads->create( 'fib', 35 );
my $thr3 = threads->create( 'fib', 35 );
$thr1->join;
$thr2->join;
$thr3->join;
And as soon as I introduce a shared variable $a, the CPU usage is somewhere between 40% and 50%:
use threads;
use threads::shared;
my $a : shared;
$a = 1000;
sub fib {
my ( $n ) = @_;
if ( $n < 2 ) {
return $n;
} else {
return $a + fib( $n - 1 ) + fib( $n - 2 ); # <-- $a was added here
}
}
my $thr1 = threads->create( 'fib', 35 );
my $thr2 = threads->create( 'fib', 35 );
my $thr3 = threads->create( 'fib', 35 );
$thr1->join;
$thr2->join;
$thr3->join;
So $a is read-only and no locking takes place, and yet the performance decreases. I’m curious why this happens.
At the moment I’m using Perl 5.10.1 under Cygwin on Windows XP. Unfortunately I couldn’t test this on a non-Windows machine with a (hopefully) more recent Perl.
Your code is a tight loop around a synchronized structure. Optimize it by having each thread copy the shared variable — just once for each thread — into an unshared variable.