Serial threads MCE::Hobo MCE::Loop MCE::Child
Linux 74.488s 25.345s 20.217s 17.932s 17.291s
macOS 84.010s 24.844s 24.505s 23.786s 23.069s
Windows 102.055s 29.702s 37.913s 28.376s 27.839s
Cygwin 162.474s ------- 50.092s 45.318s 43.949s
FreeBSD 107.569s ------- 31.138s 30.530s 30.050s
threads is slow on Cygwin, so stopped due to taking too long.
My FreeBSD has an older Thread::Queue missing the ->end method.
####
use strict;
use warnings;
use Time::HiRes 'time';
my @tokens = ('aaa'...'zzz');
my $start = time;
sub build_regex {
my ($token) = @_;
chop $token;
$token .= 'a';
}
my %result;
foreach my $token ( @tokens ) {
my $regex = build_regex($token);
my @line_results = grep { $_ ne $token and /$regex/ } @tokens;
$result{$token} = \@line_results if @line_results;
};
printf "duration: %0.03f seconds\n", time - $start;
print scalar(keys %result), "\n"; # 16900
####
use strict;
use warnings;
use threads;
use Thread::Queue;
use Time::HiRes 'time';
my $workQueue = Thread::Queue->new();
my $doneQueue = Thread::Queue->new();
my $numWorkers = 4;
my @tokens = ('aaa'...'zzz');
my $start = time;
sub build_regex {
my ($token) = @_;
chop $token;
$token .= 'a';
}
threads->create(sub{DoWork($workQueue, $doneQueue)}) for 1..$numWorkers;
$workQueue->enqueue($_) for @tokens;
$workQueue->end();
my $count_finished = 0;
my %result;
while () {
my ($key, $val) = $doneQueue->dequeue(2);
last if (!$key && ++$count_finished == $numWorkers);
$result{$key} = $val if $key;
}
$_->join() for threads->list;
printf "duration: %0.03f seconds\n", time - $start;
print scalar(keys %result), "\n"; # 16900
exit;
sub DoWork {
my ($work, $done) = @_;
while (my $token = $work->dequeue()) {
my $regex = build_regex($token);
my @line_results = grep { $_ ne $token and /$regex/ } @tokens;
$done->enqueue($token => \@line_results) if @line_results;
}
$done->enqueue(0,0);
}
####
use strict;
use warnings;
use MCE::Hobo;
use MCE::Shared;
use Time::HiRes 'time';
my $workQueue = MCE::Shared->queue();
my $doneQueue = MCE::Shared->queue();
my $numWorkers = 4;
my @tokens = ('aaa'...'zzz');
my $start = time;
sub build_regex {
my ($token) = @_;
chop $token;
$token .= 'a';
}
MCE::Hobo->create(sub{DoWork($workQueue, $doneQueue)}) for 1..$numWorkers;
$workQueue->enqueue($_) for @tokens;
$workQueue->end();
my $count_finished = 0;
my %result;
while () {
my ($key, $val) = $doneQueue->dequeue(2);
last if (!$key && ++$count_finished == $numWorkers);
$result{$key} = $val if $key;
}
$_->join() for MCE::Hobo->list;
printf "duration: %0.03f seconds\n", time - $start;
print scalar(keys %result), "\n"; # 16900
exit;
sub DoWork {
my ($work, $done) = @_;
while (my $token = $work->dequeue()) {
my $regex = build_regex($token);
my @line_results = grep { $_ ne $token and /$regex/ } @tokens;
$done->enqueue($token => \@line_results) if @line_results;
}
$done->enqueue(0,0);
}
####
use strict;
use warnings;
use MCE::Loop;
use Time::HiRes 'time';
my @tokens = ('aaa'...'zzz');
my $start = time;
sub build_regex {
my ($token) = @_;
chop $token;
$token .= 'a';
}
MCE::Loop->init(
chunk_size => 1,
max_workers => 4,
);
my %result = mce_loop {
my $token = $_;
my $regex = build_regex($token);
my @line_results = grep { $_ ne $token and /$regex/ } @tokens;
MCE->gather( $token => \@line_results ) if @line_results;
} @tokens;
MCE::Loop->finish;
printf "duration: %0.03f seconds\n", time - $start;
print scalar(keys %result), "\n"; # 16900
####
use strict;
use warnings;
use MCE::Child;
use MCE::Channel;
use Time::HiRes 'time';
my $workQueue = MCE::Channel->new(impl => 'Mutex');
my $numWorkers = 4;
my @tokens = ('aaa'...'zzz');
my $start = time;
sub build_regex {
my ($token) = @_;
chop $token;
$token .= 'a';
}
MCE::Child->create(sub{DoWork($workQueue)}) for 1..$numWorkers;
$workQueue->enqueue($_) for @tokens;
$workQueue->end();
my %result = map { %{ $_->join() } } MCE::Child->list;
printf "duration: %0.03f seconds\n", time - $start;
print scalar(keys %result), "\n"; # 16900
exit;
sub DoWork {
my ($workQueue) = @_;
my %result; # store locally
while (my $token = $workQueue->dequeue()) {
my $regex = build_regex($token);
my @line_results = grep { $_ ne $token and /$regex/ } @tokens;
$result{$token} = \@line_results if @line_results;
}
return \%result;
}