MCE::Candy(3)
π MCE::Candy β the manual page, but make it bestie-coded π
okay so you're looking at MCE::Candy(3), which is one of the User Contributed Perl Documentation pages. yes girl, somebody contributed this and we are so grateful. sit down, grab a lil snack π, and let's get into it.
β¨ NAME β¨
MCE::Candy β sugar methods and output iterators. that's the whole vibe. π¬
π VERSION π
this doc describes MCE::Candy version 1.902. iconic. no cap.
πΈ DESCRIPTION πΈ
so basically this module hands you a whole lil collection of sugar methods plus some genuinely helpful output iterators, and the iterators are the ones that keep your output in order. like, the correct order. the order you deserve. π
π₯ FOR" SUGAR METHODS π₯
ngl these sugar methods are vintage β they were created before the 1.5 release, which is the release that added MCE Models. and listen: this module loads itself automatically the moment you call a "for" method. it's giving main character energy that shows up uninvited but slays anyway. β¨
$mce->forchunk ( $input_data [, { options } ], sub { ... } )
okay so forchunk, foreach, and forseq are all sugar methods in MCE. here's the tea π«: workers get spawned automatically, the code block runs in parallel, and then shutdown gets called. so likeβ¦
do NOT call these methods if your workers need to persist afterwards. fr fr. they will get shut down. π
specifying options? optional. valid options are the same ones as for the process method.
## Declare a MCE instance.
my $mce = MCE->new(
max_workers => $max_workers,
chunk_size => 20
);
## Arguments inside the code block are the same as passed to user_func.
$mce->forchunk(\@input_array, sub {
my ($mce, $chunk_ref, $chunk_id) = @_;
foreach ( @{ $chunk_ref } ) {
MCE->print("$chunk_id: $_\n");
}
});
## Input hash, current API available since 1.828.
$mce->forchunk(\%input_hash, sub {
my ($mce, $chunk_ref, $chunk_id) = @_;
for my $key ( keys %{ $chunk_ref } ) {
MCE->print("$chunk_id: [ $key ] ", $chunk_ref->{$key}, "\n");
}
});
## Passing chunk_size as an option.
$mce->forchunk(\@input_array, { chunk_size => 30 }, sub { ... });
$mce->forchunk(\%input_hash, { chunk_size => 30 }, sub { ... });
$mce->foreach ( $input_data [, { options } ], sub { ... } )
foreach is lowkey committed to chunk_size => 1 and it cannot be overwritten. periodt. so you don't need to loop inside the block at all, bestie. and heads up β unlike forchunk up there, a hash reference as input data isn't allowed. π«
my $mce = MCE->new(
max_workers => $max_workers
);
$mce->foreach(\@input_data, sub {
my ($mce, $chunk_ref, $chunk_id) = @_;
my $row = $chunk_ref->[0];
MCE->print("$chunk_id: $row\n");
});
$mce->forseq ( $sequence_spec [, { options } ], sub { ... } )
a sequence can be defined using an array or a hash reference. choose your fighter. πͺ
my $mce = MCE->new(
max_workers => 3
);
$mce->forseq([ 20, 40 ], sub {
my ($mce, $n, $chunk_id) = @_;
my $result = `ping 192.168.1.${n}`;
...
});
$mce->forseq({ begin => 15, end => 10, step => -1 }, sub {
my ($mce, $n, $chunk_id) = @_;
print $n, " from ", MCE->wid, "\n";
});
the $n_seq variable points to an array_ref of sequences. and the chunk size? it defaults to 1 when you don't specify it. π
$mce->forseq([ 20, 80 ], { chunk_size => 10 }, sub {
my ($mce, $n_seq, $chunk_id) = @_;
for my $n ( @{ $n_seq } ) {
my $result = `ping 192.168.1.${n}`;
...
}
});
π¦ OUTPUT ITERATORS WITH INPUT π¦
this module gives you three output iterators that are genuinely so useful for preserving output order while you're gathering data. π«Ά
the chunk_id value must be the first argument to gather. and gather must be called once and not more inside the block. that's the rule, i don't make 'em, i just vibe with 'em. π
gather => MCE::Candy::out_iter_array( \@array )
this example uses the Core API with chunking disabled β basically setting chunk_size to 1.
use MCE;
use MCE::Candy;
my @results;
my $mce = MCE->new(
chunk_size => 1, max_workers => 4,
gather => MCE::Candy::out_iter_array(\@results),
user_func => sub {
my ($mce, $chunk_ref, $chunk_id) = @_;
$mce->gather($chunk_id, $chunk_ref->[0] * 2);
}
);
$mce->process([ 100 .. 109 ]);
$mce->shutdown();
print "@results", "\n";
-- Output
200 202 204 206 208 210 212 214 216 218
chunking might be the move when you're dealing with thousands or more items β like, you wanna reduce the overhead placed on IPC. π
use MCE;
use MCE::Candy;
my @results;
my $mce = MCE->new(
chunk_size => 100, max_workers => 4,
gather => MCE::Candy::out_iter_array(\@results),
user_func => sub {
my ($mce, $chunk_ref, $chunk_id) = @_;
my @output;
foreach my $item (@{ $chunk_ref }) {
push @output, $item * 2;
}
$mce->gather($chunk_id, @output);
}
);
$mce->process([ 100_000 .. 200_000 - 1 ]);
$mce->shutdown();
print scalar @results, "\n";
-- Output
100000
gather => MCE::Candy::out_iter_callback( \&cb_func )
MCE workers pass arguments for the callback function. and the chunk_id argument you give to gather is used internally for calling the callback function orderly. β¨
Current API available since 1.897.
use MCE;
use MCE::Candy;
my @results;
my $max_status = 0;
sub upd_vars {
push @results, @{ $_[0] };
$max_status = $_[1] if ($_[1] > $max_status);
}
my $mce = MCE->new(
chunk_size => 100, max_workers => 4,
gather => MCE::Candy::out_iter_callback(\&upd_vars),
user_func => sub {
my ($mce, $chunk_ref, $chunk_id) = @_;
my @output;
foreach my $item (@{ $chunk_ref }) {
push @output, $item * 2;
}
my $status = $mce->chunk_id == 3 ? 2 : 0;
$mce->gather($chunk_id, [ @output ], $status);
}
);
$mce->process([ 100_000 .. 200_000 - 1 ]);
$mce->shutdown();
print scalar @results, "\n";
print $max_status, "\n";
-- Output
100000
2
gather => MCE::Candy::out_iter_fh( $fh )
okay let's switch things up a bit and use MCE::Flow for the next 2 examples. and for the first one, chunking is not desired. π«
use MCE::Flow;
use MCE::Candy;
open my $fh, '>', '/tmp/foo.txt';
mce_flow {
chunk_size => 1, max_workers => 4,
gather => MCE::Candy::out_iter_fh($fh)
},
sub {
my ($mce, $chunk_ref, $chunk_id) = @_;
$mce->gather($chunk_id, $chunk_ref->[0] * 2, "\n");
}, (100 .. 109);
close $fh;
-- Output sent to '/tmp/foo.txt'
200
202
204
206
208
210
212
214
216
218
gather => MCE::Candy::out_iter_fh( $io )
same thing, bestie, but an "IO::*" object that can "print" is supported since MCE 1.845. π
use IO::All;
use MCE::Flow;
use MCE::Candy;
my $io = io('/tmp/foo.txt'); # i.e. $io->can('print')
mce_flow {
chunk_size => 1, max_workers => 4,
gather => MCE::Candy::out_iter_fh($io)
},
sub {
my ($mce, $chunk_ref, $chunk_id) = @_;
$mce->gather($chunk_id, $chunk_ref->[0] * 2, "\n");
}, (100 .. 109);
$io->close;
-- Output sent to '/tmp/foo.txt'
200
202
204
206
208
210
212
214
216
218
chunking is the move for the next example, because we're processing many thousands. π₯
use MCE::Flow;
use MCE::Candy;
open my $fh, '>', '/tmp/foo.txt';
mce_flow {
chunk_size => 100, max_workers => 4,
gather => MCE::Candy::out_iter_fh( $fh )
},
sub {
my ($mce, $chunk_ref, $chunk_id) = @_;
my @output;
foreach my $item (@{ $chunk_ref }) {
push @output, ($item * 2) . "\n";
}
$mce->gather($chunk_id, @output);
}, (100_000 .. 200_000 - 1);
close $fh;
print -s '/tmp/foo.txt', "\n";
-- Output
700000
π OUTPUT ITERATORS WITHOUT INPUT π
plot twist: input data is not a requirement for using the output iterators. the 'chunk_id' argument to gather is still needed and set uniquely β same as 'wid' when you're not processing input data. iykyk. π
gather => MCE::Candy::out_iter_array( \@array )
gather => MCE::Candy::out_iter_callback( \&cb_func )
use MCE::Flow;
use MCE::Candy;
my @results;
sub append_results {
push @results, $_[0];
}
mce_flow {
max_workers => 'auto', ## Note that 'auto' is never greater than 8
gather => MCE::Candy::out_iter_array(\@results),
# gather => MCE::Candy::out_iter_callback(\&append_results),
},
sub {
my ($mce) = @_; ## This line is not necessary
## Calling via module okay; e.g: MCE->method
## Do work
## Sending a complex data structure is allowed
## Output will become orderly by iterator
$mce->gather( $mce->wid, {
wid => $mce->wid, result => $mce->wid * 2
});
};
foreach my $href (@results) {
print $href->{wid} .": ". $href->{result} ."\n";
}
-- Output
1: 2
2: 4
3: 6
4: 8
5: 10
6: 12
7: 14
8: 16
gather => MCE::Candy::out_iter_fh( $fh )
use MCE::Flow;
use MCE::Candy;
open my $fh, '>', '/tmp/out.txt';
mce_flow {
max_workers => 'auto', ## See get_ncpu in <MCE::Util|MCE::Util>
gather => MCE::Candy::out_iter_fh($fh)
},
sub {
my $output = "# Worker ID: " . MCE->wid . "\n";
## Append results to $output string
$output .= (MCE->wid * 2) . "\n\n";
## Output will become orderly by iterator
MCE->gather( MCE->wid, $output );
};
close $fh;
-- Output
# Worker ID: 1
2
# Worker ID: 2
4
# Worker ID: 3
6
# Worker ID: 4
8
# Worker ID: 5
10
# Worker ID: 6
12
# Worker ID: 7
14
# Worker ID: 8
16
π INDEX π
MCE, MCE::Core β go look at those next, bestie. π«Ά
π AUTHOR π
Mario E. Roy, <marioeroy AT gmail DOT com>
and that's the whole page!! π this doc is from perl v5.42.0, dated 2025-09-10, and it's the MCE::Candy(3) manual. go forth and keep your output orderly, queen. π
β¨π¦
π¦ where this page comes from
- fedora 43: perl-MCE 1.902-1.fc43 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms