I have lots of hosts (around 40000+) that i need to test for ping using a perl script. There's a requirement to complete this verification before 3-4 minutes and i need to write/dump the ping results/output to a flat file. Another integration will be reading this output (may be tail) and generate some alerts.
I will be running this perl script on a machine with 16 CPU's (1 Socket, 8 Core's per Socket, and 2 Threads per Core). I have perl 5, version 14, subversion 1 (v5.14.1) I have used 'nmap' utility and i have timing like below:
Nmap done: 50233 IP addresses (39313 hosts up) scanned in 356.54 seconds ~ 6 Minutes
Nmap done: 79195 IP addresses (28178 hosts up) scanned in 641.93 seconds ~ 11 Minutes
Can I use multithreaded perl
to speed up further? I have the Net::Ping module installed, but I am not interested in installing more custom modules.
Update##1
Based on 'Sobrique's' answer and sample code, I have the code like below that's working. Thanks a lot for sample as it helped me to know about Thread::Queue module in perl.
#!/usr/bin/perl
# Run under Oracle Perl, for DBI.
BEGIN {
my $ORACLE_HOME = "/opt/oracle/app/oracle/product/12.1.0/client_1";
$ENV{ORACLE_HOME}=$ORACLE_HOME;
die "ORACLE_HOME not set\n" unless $ENV{ORACLE_HOME};
unless ($ENV{OrAcLePeRl}) {
$ENV{OrAcLePeRl} = "$ENV{ORACLE_HOME}/perl";
$ENV{PERL5LIB} =
"$ENV{PERL5LIB}:$ENV{OrAcLePeRl}/lib:$ENV{OrAcLePeRl}/lib/site_perl";
$ENV{LD_LIBRARY_PATH} =
"$ENV{LD_LIBRARY_PATH}:$ENV{ORACLE_HOME}/lib32:$ENV{ORACLE_HOME}/lib";
exec "$ENV{OrAcLePeRl}/bin/perl", $0, @ARGV;
}
}
use strict;
use warnings;
use threads;
use Thread::Queue;
my $process_q = Thread::Queue->new();
#insert tasks into thread queue.
open( my $input_fh, "<", "server_list" ) or die $!;
$process_q->enqueue(<$input_fh>);
close($input_fh);
my $OutputFile = "PingOutput.mout";
open (OUTPUT_FILEH, ">>$OutputFile") or die "Can't Open $OutputFile : $!";
# Worker threads
my $thread_limit = 25;
# send markers.
$process_q->enqueue(undef) for 1..$thread_limit;
my @thr = map {
threads->create(sub {
while (defined (my $server = $process_q->dequeue())) {
chomp($server);
print OUTPUT_FILEH threads->self()->tid() . ":pinging$server\n";
my $result = `/usr/bin/ping -c 1 $server`;
print OUTPUT_FILEH $result;
}
});
} 1..$thread_limit;
# terminate.
$_->join() for @thr;