pperl 0.6.3#

2026-07-18 to 2026-07-23, 35 commits.

Language and runtime#

  • Start-up: pperl starts no worker threads until a loop first runs in parallel, so a program that never does starts none; creating them took about 1 ms of every start. In the benchmark suite’s start-up rows pperl went from 1.277 to 1.136 times perl5’s start-up time (geometric mean).

JIT and parallelization#

  • Subroutines called from compiled loops compile together with the loop when their body contains loops of its own (while, C-style for, ranges, nested loops) or reads a lexical variable of the enclosing scope, a closure.

  • Array references in compiled loops: for (@$A), $A->[$i][$j] and loop bounds such as scalar(@$A) compile, so matrix code written over arrays of arrays, such as a matrix difference or a matrix product’s triple loop, compiles as one nest of loops.

  • Hashes in compiled loops: hash elements with computed keys, such as $h{$i & 1023}, can be read and written in a compiled loop, and %h = (key => value, ...) with constant keys and numeric values compiles too.

  • Strings in compiled loops: substr, uc, lc, ucfirst, lcfirst and reverse compile as parts of larger expressions, as in length(substr($s, 0, $n)), and so do string comparisons and concatenations of array elements. Loops whose condition is a pattern match without /g or a length, such as while ($s =~ /x/) or while (length $s), compile.

  • Nested loops: C-style for (;;) loops nested in other loops compile. Whether a loop is worth compiling is judged by the work of its body, inner loops included, so for (0..10) { for (0..9999) {...} } compiles although its outer loop runs only 11 times.

  • do {...} while and do {...} until loops compile.

  • map and grep statements of the form @dst = map {...} @src compile on their own, outside any loop, when the source array is large enough to repay the compilation.

  • More loops compile: whether a loop compiled could depend on the code around it, for example on a preceding statement with a ?: conditional; such loops now compile. So do loops that use the result of a comparison as a number, as in $n += ($x > $y) or $a[$i == 0].

  • Parallel reductions over arrays: a loop that adds up values read from arrays it does not write, such as $sum += $a[$i], runs in parallel on several cores.

  • JIT compilation cost: finding and compiling a program’s loops takes less time. A program of 600 short loops ran in 0.371 s instead of 0.577 s, and the search for loops now grows with the size of the program rather than with its square.

Modules#

  • MIME::Base64: encode_base64 encodes inputs of 1 MiB and more on several cores, with output identical to the serial encoder; on 32 MiB it is 2.85 times as fast as perl5’s MIME::Base64.

  • Digest::SHA: methods that return their object, such as add, kept an extra reference to it, so a Digest::SHA object was never freed.

  • POSIX: POSIX::read accepts a reference to its buffer as well as the buffer itself, as on perl5, and the data it reads is tainted under -T.

  • PDL: lu_backsub given its right-hand side as a plain Perl value no longer reads freed memory.

Command line#

  • Version reporting: pperl -v and pperl -V name perl 5.44 as the version pperl is compatible with, and $Config{version} is 5.44.99, matching $^V; all three said 5.42.0.

Documentation#

  • Translations: the “Graphics with Perl” guide is translated into German, French, Italian, Czech, Greek, Danish, Hebrew, Ukrainian, Croatian and Spanish.