Performance#

How to make Perl run fast on pperl, and - just as important - how to tell whether it already does. This guide is the actionable layer: where the classic Perl performance advice still holds, where pperl’s JIT and auto-parallelizer have quietly made it irrelevant, and where pperl rewards code shaped in ways upstream Perl never cared about.

It is deliberately not a tour of the machinery. The JIT, the parallel scheduler, the native-module dispatch and the FFI each have their own chapter in the architecture guide; this guide tells you what to write so they fire, and points at those chapters for the why.

Who this is for#

A working Perl programmer with a program that is too slow, or one they want to keep fast. You know how to write the code; you want to know which habits pay off here, which are now dead weight, and how to measure the difference without guessing.

You do not need to understand Cranelift, Rayon, or the interpreter’s inner loop. Where a behaviour depends on them, this guide states the behaviour and links the chapter that explains it.

The one rule that survives everything#

Measure first. Every other rule in this guide is conditional on a measurement you have not yet taken. Perl performance intuition, honed on the upstream interpreter, mispredicts on pperl in both directions: code you expect to be slow is sometimes compiled to native machine code and runs faster than C; code you expect the JIT to rescue sometimes falls back to the interpreter because one string operation crept into a numeric loop.

The profiler does not lie and your intuition, ported from another runtime, does. Start at Measuring.

How this guide is organised#

  • Measuring - the tools that actually work under pperl. The upstream XS profilers (Devel::NYTProf) do not load; the built-in --features=profile build and the bench/run-perlbench runner do. How to read their output and how to A/B two versions of a routine.

  • Idioms - a triage of the classic Perl performance idioms. Each is tagged: still valid, made moot by the JIT or parallelizer, or newly relevant because of how pperl compiles. The idioms that were folklore on upstream Perl are not all folklore here.

  • Sorting - sort in depth: the Schwartzian transform, the Guttman-Rosler transform, sort subroutine cost, and when the comparator is the bottleneck.

  • Writing fast pperl - the positive program: how to structure a hot loop so the JIT compiles it, how to shape a reduction so the parallelizer claims it, and the one mistake - mixing string work into a numeric loop - that silently disables both.

What this guide does not cover#

The mechanisms live elsewhere and this guide does not repeat them:

  • JIT compilation - what gets compiled, the caching model, the variable-type analysis.

  • Parallel execution - the reduction analysis, the side-effect gate, the CLI thread controls.

  • Regex performance - backtracking, catastrophic patterns, the engine’s optimiser. Regex speed is its own discipline; nothing in this guide duplicates it.

  • Native modules - why List::Util and friends run at built-in speed with no XS layer.

  • Auto-FFI - calling C without XS, and the per-call marshalling cost that makes it the wrong tool for a hot inner loop.

A note on numbers#

Concrete speedups in this guide are reproduced from the architecture and concurrency chapters, which carry the measured figures and the benchmark that produced them. Where this guide states a speedup without a number, the qualitative behaviour is established but the exact figure depends on your machine, your data, and your build - run bench/run-perlbench and trust your own measurement over any printed ratio.