Please find below various demonstrations. Increase the loop iteration from 1e5 to 1e6 and watch top or task manager.
#!/usr/bin/env perl
use strict;
use warnings;
use MCE::Hobo;
use MCE::Shared;
use Time::HiRes qw(time);
use feature qw(say);
my $number = MCE::Shared->scalar(0);
my $start = time;
MCE::Hobo->create('task', $_) for 1 .. 4;
MCE::Hobo->waitall;
printf "duration: %0.3f seconds\n", time - $start;
say "number: ", $number->get();
sub task {
my ($id) = @_;
say "Hobo $id started";
$number->incr() for 1 .. 100000;
say "Hobo $id ended";
}
__END__
Hobo 1 started
Hobo 2 started
Hobo 3 started
Hobo 4 started
Hobo 4 ended
Hobo 2 ended
Hobo 1 ended
Hobo 3 ended
duration: 0.872 seconds
number: 400000
Fetching data involves extra latency due to workers waiting for a response from the shared-manager process. No worries, it runs reasonably well for being a plain-Perl module.
sub task {
my ($id, $val) = @_;
say "Hobo $id started";
$val = $number->incr() for 1 .. 100000;
say "Hobo $id ended";
}
__END__
Hobo 1 started
Hobo 2 started
Hobo 3 started
Hobo 4 started
Hobo 4 ended
Hobo 3 ended
Hobo 1 ended
Hobo 2 ended
duration: 2.183 seconds
number: 400000
Dereferencing involving a fetch and store requires a mutex. Overhead goes up the roof. There's now a mutex lock, TIE STORE + FETCH (2 IPCs for that), and finally a mutex unlock.
#!/usr/bin/env perl
use strict;
use warnings;
use MCE::Hobo;
use MCE::Mutex;
use MCE::Shared;
use Time::HiRes qw(time);
use feature qw(say);
my $mutex = MCE::Mutex->new( impl => 'Channel' );
my $number = MCE::Shared->scalar(0);
my $start = time;
MCE::Hobo->create('task', $_) for 1 .. 4;
MCE::Hobo->waitall;
printf "duration: %0.3f seconds\n", time - $start;
say "number: ", $number->get();
sub task {
my ($id, $val) = @_;
say "Hobo $id started";
for ( 1 .. 100000 ) {
$mutex->lock;
$val = ++${ $number };
$mutex->unlock;
}
say "Hobo $id ended";
}
__END__
Hobo 1 started
Hobo 2 started
Hobo 3 started
Hobo 4 started
Hobo 2 ended
Hobo 1 ended
Hobo 4 ended
Hobo 3 ended
duration: 20.343 seconds
number: 400000
Let's remove dereferencing. Thus, mutex and OO only.
sub task {
my ($id, $val) = @_;
say "Hobo $id started";
for ( 1 .. 100000 ) {
$mutex->lock;
$val = $number->incr();
$mutex->unlock;
}
say "Hobo $id ended";
}
__END__
Hobo 1 started
Hobo 2 started
Hobo 3 started
Hobo 4 started
Hobo 3 ended
Hobo 4 ended
Hobo 1 ended
Hobo 2 ended
duration: 9.702 seconds
number: 400000
Summary
Performance is possible via the OO interface. Dereferencing is nice if you need it. Mutex is possible as well for synchronization. Any fetch from the shared-manager takes extra time. MCE::Shared is fully wantarray aware. Meaning, the MCE::Shared engine will only do extra stuff whenever needed, not more.
Regards, Mario.
-
Are you posting in the right place? Check out Where do I post X? to know for sure.
-
Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
<code> <a> <b> <big>
<blockquote> <br /> <dd>
<dl> <dt> <em> <font>
<h1> <h2> <h3> <h4>
<h5> <h6> <hr /> <i>
<li> <nbsp> <ol> <p>
<small> <strike> <strong>
<sub> <sup> <table>
<td> <th> <tr> <tt>
<u> <ul>
-
Snippets of code should be wrapped in
<code> tags not
<pre> tags. In fact, <pre>
tags should generally be avoided. If they must
be used, extreme care should be
taken to ensure that their contents do not
have long lines (<70 chars), in order to prevent
horizontal scrolling (and possible janitor
intervention).
-
Want more info? How to link
or How to display code and escape characters
are good places to start.