pperl 0.6.17#
2026-09-06 to 2026-09-09, 96 commits.
Language and runtime#
__END__in bundled modules no longer opens aDATAhandle. A module shipped inside pperl that ends in__END__followed by POD,strictandwarningsamong them, had aDATAhandle reading that POD; as in perl5, only__DATA__gives a module aDATAhandle.
JIT and parallelization#
nbody: the Benchmarks Game’s nbody at 200,000 steps runs 293M instructions, from 2,778M. At its official 50,000,000 steps it runs 47.65G instructions in 6.36 s of CPU time, where Node.js takes 49.66G and 6.0 s. Besides the call and array work below, compiled loops keep floating-point values in registers instead of reloading them from memory, check a loop’s constant bound once instead of on every iteration, and skip checks that cannot fail, such as overflow on
$j + 1of a loop counter and the domain test onsqrtof a sum of squares. Placing the arrays’ buffers so that loads and stores to different arrays no longer stall the processor cut nbody’s CPU cycles by 18%.Calls to subroutines that loop: a compiled loop that calls a subroutine with loops of its own, such as nbody’s
advance(), now compiles together with the called body, where before each call left compiled code and entered it again twice. The subroutine’smyvariables are held in registers, and its call frame is pushed and popped inside compiled code.$_[0]in a subroutine called from one place with a numeric literal argument reads the literal directly.Arrays of numbers whose elements are all floating-point numbers, or all integers, when a compiled loop starts are read and written as flat memory, without a type check per element. For the loop’s duration such an array’s values are kept in a buffer and written back when the loop is left, and an index that is a loop counter is checked against the array’s size once, at the loop’s start. On nbody the buffer alone saves 15.3% of the instructions.
Calls to small numeric subroutines no longer leave compiled code: a loop calling a function such as
eval_Ain the Benchmarks Game’s spectral-norm, ause integerbody that reads$_[0]and$_[1]directly, passes the arguments in registers, and the function’s ownmyvariables are registers too. spectral-norm at N=500 runs 440.0M instructions, from 776.5M, and at its official N=5,500 takes 3.25 s of CPU time, from 5.33 s.Nested
whileand C-styleforloops inside a compiled loop compile as part of it, and an unlabelledlastornextout of them is a jump. The Benchmarks Game’s fannkuch-redux at n=9 runs 30.7% fewer instructions (6,650M to 4,609M).Number types after compiled loops match perl5’s.
$v = $i * 0.5andsqrt(4)stay floating-point numbers even when the result is integral, an integer literal or ause integerresult stays an integer, and an integer variable such as$t = ($i <=> 250)no longer carries a floating-point copy perl5 would not have. The values were right before; the flags, visible throughDevel::Peek, were not.Loops left half-compiled by 0.6.16 compile fully again: a loop whose variables are all assigned before they are read (
$t = ($i <=> 250)), one that updates a package variable ($G = $G + 1), and one whose counter was used as a float during its first iterations (sin($i)). They had fallen back to a slower, checked mode; for the package-variable loop that was 2.2 times the instructions.JIT compile time: a subroutine the JIT would compile and then reject as a numeric function is rejected before machine code is generated. nbody’s fixed compile cost falls from 157M to 107M instructions, and the Benchmarks Game’s mandelbrot at size 120, a run that is mostly compilation, executes 9.5% fewer instructions.
Modules#
Peta::WebGPU is new: GPU compute on the wgpu library, in builds with the
webgpufeature.Peta::WebGPU::Device->newopens a device with the adapter’s own limits, compiles WGSL shaders, creates storage and uniform buffers and pipelines, and runs compute passes;have_gpu()andadapters()report what the machine has. A shader or validation error is a Perl exception with wgpu’s message, and a method with no natural result returns its object, soor dieworks and calls chain. A PDL ndarray uploads to a buffer directly ($gpu->storage_buffer(float(1 .. 8))); a double-typed one is refused with the conversion to use, since WGSL has only 32-bit numbers.SDL2: 25 object methods that die on failure, among them
clear,copy,draw_line,fill_rect,present, thesave_*methods and everyset_*, returned nothing on success, so$ren->clear or diedied when it worked. They now return a true value, the object where there is no natural result, and calls chain:$ren->set_draw_color(30, 30, 40, 255)->clear. The directSDL_*functions still return what the C functions do.Loading modules under
-wprints no warnings perl5 does not print.use POSIX (), and with ituse Imager, printed 27: constant subroutines shared with Fcntl reported as redefined, and two “Ambiguous call resolved as CORE::open()”.use PDL; use PDL::MatrixOpsprinted 48 redefinitions,use PDL::Lite; use PDL532 anduse PDL::LiteF; use PDL631, because PDL’s sub-modules were loaded twice.PDL printing follows upstream PDL’s rules. Elements print as perl prints numbers, so
pdl(1.0) - pdl(0.88096)shows0.11904, not0.11904000000000003;$PDL::doubleformatand$PDL::floatformatexist and take effect, and$PDL::toolongtoprintis honoured. A 3-D ndarray prints as nested blocks instead of one flat list,PDL->nullasNull, an empty ndarray asEmpty[0], and a 2-D ndarray ends with its newline.PDL:
appendon a slice no longer aborts pperl andglueno longer fails with “Not physical but doesn’t have parent”; neither needs->severfirst.-=,+=,*=,/=,**=and%=on an ndarray no longer warn “Use of uninitialized value in subroutine entry”.pdl('BAD')is a 0-dimensional ndarray,pdl('[[5]]')stays 2-dimensional, andnormnormalises a vector as upstream’s does instead of dividing the whole ndarray by its Frobenius norm.use PDL ()no longer definesmain::pdl.
Documentation#
Module reference: the Imager and GD pages include documentation that was written but never published: Imager’s colour classes, its kinds of image and the channel mask, and
GD::ImageandGD::Font.Graphics guides: the 2D graphics guide is fully translated again in all 41 languages after its move to SDL2. The 3D guide’s chapter on opening a window with an OpenGL context is withdrawn, since pperl’s GPU binding is Peta::WebGPU, and the guides’ examples save their images with
$ren->save_png.