From 7ad893fdbcf0c81cfbf8bf260aa97040674a1885 Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Mon, 30 Oct 2017 10:50:56 +0100 Subject: mailer.pl: Use MCE instead of threads Faster startup, less overhead (memory) Signed-off-by: Florian Pritz --- mailer.pl | 74 ++++++++++++++++++++++----------------------------------------- 1 file changed, 26 insertions(+), 48 deletions(-) diff --git a/mailer.pl b/mailer.pl index d016673..c3b53da 100644 --- a/mailer.pl +++ b/mailer.pl @@ -1,19 +1,20 @@ #!/usr/bin/perl use warnings; use strict; -use Email::Stuffer; +use autodie; +use Data::Dumper; use Email::Sender::Transport::SMTP::Persistent; -use File::Basename; +use Email::Stuffer; use Encode; use Encode::Locale; -use File::Slurp; -use threads; -use Thread::Queue; +use Encode::MIME::Header; use Getopt::Long; +use List::Util; +use MCE; +use MCE::Loop; +use Path::Tiny; use Pod::Usage; -use Encode::MIME::Header; use Time::HiRes qw(gettimeofday tv_interval); -use Data::Dumper; use open ':encoding(locale)'; @ARGV = map { decode(locale => $_, 1) } @ARGV; @@ -28,6 +29,7 @@ my $transport = Email::Sender::Transport::SMTP::Persistent->new({ #debug => 1, }); my $thread_count = 64; +my $chunksize = 1; # #### # end config @@ -49,30 +51,22 @@ sub trim { my $subject = $opts{subject}; my $from = $opts{from}; -my @addrlist; my $content_html; my $content_txt; +my $mce_input; + if ($opts{to} =~ m/.+\@.+\..+/) { - push @addrlist, $opts{to}; + $mce_input = [$opts{to}]; } else { if (-r $opts{to}) { - open LIST, "<", $opts{to} or die; - for () { - my $to = trim($_); - next if ($to eq ""); - push @addrlist, $to; - } - close LIST; + open my $fh, "<", $opts{to}; + $mce_input = $fh; } else { print STDERR "Error: can't read recipient file: $!\n"; } } -if (0+@addrlist < $thread_count) { - $thread_count = 0+@addrlist; -} - die "Error: subject not set\n" unless ($opts{subject}); die "Error: from not set\n" unless ($opts{from}); die "Error: content-txt not set\n" unless ($opts{"content-txt"}); @@ -80,9 +74,9 @@ die "Error: can't read content-txt: $!\n" unless (-r $opts{"content-txt"}); die "Error: can't read content-html: $!\n" if ($opts{"content-html"} and not -r $opts{"content-html"}); if ($opts{"content-html"}) { - $content_html = read_file($opts{"content-html"}, binmode => ':utf8'); + $content_html = path($opts{"content-html"})->slurp_utf8; } -$content_txt = read_file($opts{"content-txt"}, binmode => ':utf8'); +$content_txt = path($opts{"content-txt"})->slurp_utf8; print "Building email ... " if $opts{debug}; @@ -99,37 +93,21 @@ $msg->transport($transport); print "done\n" if $opts{debug}; -my $q = Thread::Queue->new(); - -print "creating worker threads\n" if $opts{debug}; -for (my $i = 0; $i < $thread_count; $i++) { - my $thr = threads->new(sub { - while (my $to = $q->dequeue()) { - $msg->to($to); - $msg->send(); - print "sent mail in thread".threads->self->tid()."\n" if $opts{debug}; - } - $transport->disconnect; - }); -} +print "creating workers\n" if $opts{debug}; +MCE::Loop::init {max_workers => $thread_count, chunk_size => $chunksize}; print "Sending\n"; my $send_time = [gettimeofday]; - -for (@addrlist) { - $q->enqueue($_); -} - -$q->end(); - -# wait for everyone before exiting -foreach my $thr (threads->list) { - if ($thr->tid && !threads::equal($thr, threads->self)) { - print "waiting for thread ".$thr->tid()." to finish\n" if $opts{debug}; - $thr->join; +mce_loop { + my ($mce, $chunk_ref, $chunk_id) = @_; + for my $to (@{$chunk_ref}) { + $msg->to($to); + $msg->send(); + print "sent mail in worker ".MCE->wid." from chunk ".$chunk_id."\n" if $opts{debug}; } -} + $transport->disconnect; +} $mce_input; print "done after ".tv_interval($send_time)." seconds\n"; -- cgit v1.2.3-24-g4f1b