Performance and profiling

Contents
Measure before you change
Benchmark
Profile with NYTProf
The usual wins

Measure before you change

Perl is fast enough for most jobs, and guesses about hot spots are usually wrong. Start with a timer around the part that feels slow, and only then decide what to rewrite.

use Time::HiRes qw(time); my $start = time; my $lines = parse_log($file); printf "parsed %d lines in %.3f s\n", scalar @$lines, time - $start;

Time::HiRes gives sub-second resolution; the built-in time only counts whole seconds, which is useless for a function that takes 80 milliseconds. For a whole program, the shell already measures it:

time perl analyze.pl access.log

real 0m4.812s user 0m4.601s sys 0m0.204s

Real time includes waiting for disk and network; user time is the CPU your code burned. If user and real are close, the program is CPU-bound and code changes will help. If real is much larger, look at input and output first.

Benchmark

When two implementations look equally reasonable, race them instead of arguing. Benchmark runs each variant for a fixed time and prints a comparison table:

use Benchmark qw(cmpthese); my $text = "the quick brown fox jumps over the lazy dog. " x 2000; cmpthese(-1, { regex => sub { my $n = () = $text =~ /quick/g }, index => sub { my ($n, $pos) = (0, 0); while (($pos = index($text, "quick", $pos)) >= 0) { $n++; $pos++; } }, });

Rate regex index regex 1420/s -- -88% index 11800/s 731% --

The literal search wins because it never runs the regex engine. That does not mean every regex should become an index loop: the regex version is shorter and handles patterns that index cannot. Measure the real input before choosing.

The first run of a benchmark is always slower because of warm-up, and a busy machine adds noise. Run it twice, and ignore differences under ten percent: they are usually measurement error, not a real win.

Profile with NYTProf

A benchmark tells you which snippet is faster. A profiler tells you which part of your program is slow, including the calls you did not suspect. Devel::NYTProf is the standard choice.

cpanm Devel::NYTProf

perl -d:NYTProf bin/report.pl access.log

The run writes nytprof.out. Converting it to HTML gives a report with time per subroutine, per line, and per call site:

nytprofhtml --open

Read the report from the top: the subroutine list shows where the time went, and the line view shows which statement inside it is hot. A line called a million times for one microsecond each is a different problem from one call that takes ten seconds.

Profiling adds overhead, so measure a smaller input if the full run takes minutes. The proportions usually survive the reduction, and the hot path is the same.

The usual wins

Most slow Perl scripts are slow for one of a few reasons, and none of them is the interpreter:

my $re = qr/^\d{4}-\d{2}-\d{2}$/; # compiled once my %seen = map { $_ => 1 } @ids; # lookup later is O(1)

Use index($haystack, $needle) >= 0 instead of a regex when you search for a literal string. Use Devel::Size::total_size when memory is the limit and you need to know which structure is huge.

Finally, treat readability as a feature. A ten percent speedup that makes the code unmaintainable is a bad trade unless the program runs on every request of a busy service. Measure, fix the hot spot, measure again, and stop when it is fast enough.

Next: Modern Perl tour

Article author: Arthur Isaev

Related articles
Perl
Perl course: zero to hero in 50 lessons
What is Perl and where it runs
Install Perl and check the version
Your first Perl script
The debugger as a REPL
Scalars and sigils
Numbers
Strings
Interpolation and quoting
Arrays
push, pop, shift and splice
Hashes
keys, values, exists and delete
Scalar and list context
Conditions and comparison
while, for, next and last
foreach and the default variable
Subroutines
Arguments in @_
References
Nested data structures
Regular expressions: match and anchors
Captures and named groups
Substitution with s///
split and join
grep and map
Sort and the Schwartzian transform
Read and write files
File tests and metadata
Directories and paths
die, warn and eval
Modules and Exporter
CPAN and cpanm
Objects with bless
Modern objects with Moo
Testing with Test::More
strict, warnings and diagnostics
Options with Getopt::Long
Environment and %ENV
system, backticks and pipes
One-liners with -n and -p
CSV and TSV processing
JSON with JSON::PP
HTTP clients with HTTP::Tiny
Sockets and IO::Socket
Databases with DBI
Capstone: todo CLI
Capstone: log report
Performance and profiling
Modern Perl tour
Hero roadmap: the whole course on one page
Install Perl on Windows 11
Install Perl on Ubuntu
Install Perl on Rocky Linux
Install Perl on macOS
Install Perl on FreeBSD
Perl in Docker

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.com
Write to info@aredel.com if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: