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; }