How can I optimize this Perl script?
It takes "days of the week" such as "Mon and "Tue" or "Wed, Thu and Sun" and simply returns an integer to represent them.
use strict;
use feature qw(signatures);
use warnings;
no warnings qw(experimental::signatures);
my $DAYS_OF_WEEK_LOOKUP = ( { mon => 1, tue => 2, wed => 4, thu => 8, fri => 16, sat => 32, sun => 64 });
my $days_of_week_integer= days_of_week_to_int (['zzz', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'fri', 'SAT']);
print "$days_of_week_integer\n";
sub days_of_week_to_int ($days) {
my $day_of_week = 0;
foreach my $key (@$days) {
$day_of_week = $DAYS_OF_WEEK_LOOKUP->{lc($key)} if $DAYS_OF_WEEK_LOOKUP->{lc($key)};
}
return $day_of_week if $day_of_week < 128;
return;
}
I am always looking to understand how to optimize my code better and gain experience from seasoned developers. The script works perfectly well and well it's in Perl so it already runs very fast.
However, I can't help feeling there is a more optimum "Perl way" of achieving the same result and I wondered if anyone felt the same and could show me the way. Small tips are important tips!
Thank you to everybody and I add the final code here with the benchmarks. This is my original code with the extra overhead stripped but faithful to the original with the polar bear code.
use strict;
use Benchmark ':all';
my $polar_bitmap = 0x01;
my @polar_days_of_week = qw/Mon Tue Wed Thu Fri Sat Sun/; # USA/Canada week days order
my $orig_DAYS_OF_WEEK_LOOKUP = ( { Mon => 1, Tue => 2, Wed => 4, Thu => 8, Fri => 16, Sat => 32, Sun => 64 });
my %polar_DAYS_OF_WEEK_LOOKUP = map { $_ => ( $polar_bitmap <<= 1 ) / 2 } @polar_days_of_week;
my @days;
@days = qw/Mon Wed Tue Sat Sun Thu/;
print "orig : " . (orig_days_of_week_to_int(@days)) . "\n";
print "polar : " . (polar_days_to_mask ( \@days)) . "\n";
@days = qw/Mon Sat Sun Thu/;
print "polar : " . (polar_days_to_mask(\@days)) . "\n";
print "orig : " . (orig_days_of_week_to_int(@days)) . "\n";
@days = qw/Mon Wed Tue Sat Sun Thu/;
cmpthese(-3, {
orginal => sub { orig_days_of_week_to_int(@days) },
polar_b => sub { polar_days_to_mask(\@days) },
});
exit 0;
sub polar_days_to_mask {
my $days = shift;
my $mask;
$mask ^= $polar_DAYS_OF_WEEK_LOOKUP{$_} for @$days;
return $mask;
}
sub orig_days_of_week_to_int {
my @days = @_;
my $day_of_week = 0;
foreach my $key (@days) {
$day_of_week = $orig_DAYS_OF_WEEK_LOOKUP->{$key};
}
return $day_of_week;
}
And the output:
orig : 111
polar : 111
polar : 105
orig : 105
Rate orginal polar_b
orginal 1411082/s -- -41%
polar_b 2398719/s 70% --
I've added the code above just in case I messed anything up as you always should be careful with BenchMarks! :-)
And to show that above point... I thought I would test it with a LINODE node that I have...
Rate orginal polar_b
orginal 741061/s -- -25%
polar_b 992490/s 34% --
Actually, compared to my HP bare-metal at home... the LINODE gives me say 34% consistently and my home machine 70%. (same o/s, same versions)
So there you are...be wary of Benchmarks!
Never the less, part man, part bear, part AI, the Polar solution was coool.
CodePudding user response:
I haven't done any benchmarking, but I think this is cleaner (Notes in comments):
#!/usr/bin/env perl
use strict;
use warnings;
use experimental qw/signatures/; # Instead of use feature and no warnings
use feature qw/say/;
use List::Util qw/sum0/;
# Plain hash instead of hashref
my