Daniel's Perl5 Page

Table of contents:

Perl Best Practices (PBP)

Check code:
perlcritic -1 mymodule.pm
Perl tidy setup (.perltidyrc):
-l=78
-i=4
-ci=4
-st
-se
-vt=2
-cti=0
-pt=1
-bt=1
-sbt=1
-bbt=1
-nsfs
-nolq
-wbb="% + - * / x 1= == >= <= = + !~ < > | & **= += *= &= <<= &&= -= /= |= >>= ||= .= %= ^= x= //="
VIM setup (.vimrc):
set background=dark
set ai
set showmatch
set tabstop=4
set shiftwidth=4
set expandtab

ModPerl

ModPerl does not handle all HTTP status codes correctly:
...
sub fix_modperl_response {
    my ($cgi, $header) = @_;
    if ($ENV{MOD_PERL}) {
        # special HTTP response codes:
        my $stat200re = qr{(?:20[16789]|2[1-9])}xms;
        my $stat300re = qr{(?:30[89]|3[1-9])}xms;
        my $stat400re = qr{(?:41[89]|4[2-9])}xms;
        my $stat500re = qr{(?:50[6-9]|5[1-9])}xms;
    
        if (${header}{-Content_length} > 0 
                && ${header}{-status} =~ /^(?:$stat200re|$stat300re|$stat400re|$stat500re)/xms
                && ${header}{-status} =~ /^(\d)/xms 
           ) {
            $cgi->r->status("${1}00");
        }
    }
    return;
}

...

my $cgi = CGI->new();
my %header = { -status=> '201', -Content_length=>100 };


# yes, first print header and content:
print $cgi->header(%header);
...

# after that fix the HTTP status code in response:
fix_modperl_response($cgi, \%header);

...
ModPerl has some trouble to read request body data from stdin with <>:
...
sub read_request_body {
    my $body = q{};
    while ( read STDIN, my $buffer, 1_048_576 ) {
        $body .= $buffer;
    }
    return $body;
}
...

Profiling

To profile a Perl program with NYTProf change shebang to (or use Perl command line parameter '-d:NYTProf'):
#!/usr/bin/perl -d:NYTProf
The NYTProf profiler creates a nytprof.out file that can be converted to other formats like HTML or Callgrind, for example:
nytprofcg nytprof.out
The Callgrind file nytprof.callgrind can be opened with kcachegrind:
kcachegrind nytprof.callgrind

Benchmark

Sometimes it's unclear how fast code is and to check it use "Benchmark":
#!/usr/bin/perl
use strict;
use warnings;
use Benchmark qw(cmpthese);
our $VERSION = '1.0';
sub read_file {
    my ( $file, $bufsize ) = @_;
    my $buffer;
    if ( open my $fh, '<', $file ) {
        binmode $fh;

        while ( my $bytesread = read $fh, $buffer, $bufsize ) {

            # do nothing yet
        }
        close($fh) || carp("Cannot close $file.");
    }
    else {
        croak("Cannot open $file");
    }
    return;
}
my $fn = '/tmp/readtest.data';
cmpthese(
    -2,
    {
        bufsize1024    => sub { read_file( $fn, 1_024 ); },
        bufsize4096    => sub { read_file( $fn, 4_096 ); },
        bufsize16384   => sub { read_file( $fn, 16_384 ); },
        bufsize32768   => sub { read_file( $fn, 32_768 );},
        bufsize65536   => sub { read_file( $fn, 65_536 ); },
        bufsize1048576 => sub { read_file( $fn, 1_048_576 ); },
    }
);

Memory holes

Long running Perl scripts like ModPerl CGI scripts or server scripts should be checked for memory holes.

File handling (*STDIN, *STDOUT, *STDERR too)

Integrated Development Environment (IDE)

Examples


© Daniel Rohde | created: November, 9th 2016 | changed: November, 23th 2017