pperl 0.6.12+ - "Shall we play a game?"

There is no release attached to this post - the second half will explain why. It is a post about measurement, twice over. Earlier posts claimed that pperl is under high-velocity development, and a claim like that should be quantified - so we do, with the same statistics perl's own release notes use, epigraph included. And we have started playing the Computer Language Benchmarks Game: one program is finished, the result is a 36x speedup on the game's terms, and the conclusions have reset our speed goals.

The epigraph, answered

Perl release announcements traditionally open with an epigraph, a short quotation the release manager chooses. For 5.44.0, Leon Timmermans chose Frank Herbert's Dune:

Once men turned their thinking over to machines in the hope that this would set them free. But that only permitted other men with machines to enslave them.

It is a nice touch with all these thinking machines around these days. Given pperl currently tracks 5.44, we think our epigraph should remain within the same universe:

"We have just folded space from Ix... Many machines on Ix... new machines. Better than those on Richesse."

Velocity, in perldelta units

Every perl release closes its perldelta with the same paragraph of statistics. For 5.44.0 it reads:

Perl 5.44.0 represents approximately 12 months of development since Perl 5.42.0 and contains approximately 270,000 lines of changes across 1,300 files from 71 authors.

Excluding auto-generated files, documentation and release tools, there were approximately 110,000 lines of changes to 860 .pm, .t, .c and .h files.

The same yardstick, applied to pperl per release sprint. Counting is the tree diff between the two release commits, over half-open ranges, so consecutive sprints neither overlap nor leave a gap. The code columns apply the same exclusions as perl's second sentence - no auto-generated files, no documentation, no assets, no vendored modules, no tooling; .rs, .pl, .pm and .t files only:

sprintdayscommitslinesfilescode linescode files
0.5.0 .. 0.6.01064038,756,00043,000254,000770
0.6.0 .. 0.6.8161531,389,00020,000270,000595
0.6.8 .. 0.6.xx132941,889,00027,000105,000475

Held against the quote above: the 16 days between 0.6.0 and 0.6.8 contain about as many lines of code change - 270,000 - as perl 5.44.0 reports for twelve months of changes of every kind, and the 13 days since 0.6.8 roughly match perl's full-year code figure. That is what "high-velocity development" means here: currently, about one perl-year of code change every two weeks. Greenfield churn is not mature-project maintenance, and we are not 71 authors - of course.

Two footnotes: the gross figures are mostly documentation, since the manual ships in English and 41 translated locales; and all of it lands under a harness - some 1,800 test files comparing pperl's output against perl 5.44 byte for byte, over a runtime of roughly 800,000 lines of Rust.

The Benchmarks Game

The Computer Language Benchmarks Game is the longest-running cross-language benchmark in public view: fixed problems, published source, any language, strict rules about keeping the same algorithm. Perl's standing there is not a secret. On nbody, the site lists C at about 2.1 s, node.js at about 8.6 s, and the fastest Perl entry at about seven minutes - 215x behind C.

The film our title borrows from concluded that the only winning move is not to play, and that has largely been Perl's relationship with the Game: the entries are old, the rankings are what they are, and the results get cited mainly by people arguing against Perl. With a JIT in the runtime, not playing stopped being the rational move. So we play - under house rules that keep the game from turning into solitaire:

  • Any entry we measure is Perl that implements the same algorithm as the published one, runs on perl5 too, and produces byte-identical output on both runtimes, at every input size.
  • The JIT is not shaped around the Game's programs, nor the programs around the JIT: every gap a program exposes is fixed as a general construct, or not at all.

The threads obstacle. The Game allows hand-threaded entries, and the strong Perl entries use ithreads - mandelbrot, the program this post reports, included. pperl is deliberately non-threaded; its parallelism is Rayon inside the runtime, not a thread API in the language, so the published entry cannot run on it at all. The rules permit different code as long as the algorithm is the same, and they do not require a parallel program either - some published entries are serial. We stay inside those lines: our rewrite keeps the kernel byte-identical and replaces the thread pool with a plain loop over scanlines, output pixel-identical. The eventual pperl entry will be more idiomatic, plainer Perl than today's highly optimized one - that is the point of a runtime that does the optimizing. On perl5 both versions run, which keeps the bracket visible - four threads for the published entry, one for the rewrite may be enough, more are an option.

The result, in ballpark. Identical algorithm, single-threaded, the JIT runs mandelbrot around 36x faster than perl5 - with --no-jit at perl5 parity as the control, so the win is the compiler, not baseline games. One pperl core beats the published entry's four threads in wall clock, and by an order of magnitude in CPU time - and the parallelizer contributes nothing here yet, so that is one core with more still on the table. The reading that matters most: the nearest runtime still ahead of us on this kernel is node.js, within a factor of 1.5 - the competition has moved from perl5 to V8.

And that is the promised explanation for the missing release. Playing the Game reset the goal: the reference for a JIT-equipped pperl is no longer perl5, it is the fastest scripted language of the day - which, more often than not, means node.js and its V8. Competing there takes more than closing gaps one by one, so we have started the pperl JIT architecture from scratch - again. Releases resume when the rebuild lands.

One more design decision belongs in that explanation. Benchmarks may or may not translate to real-world programs, so the new JIT is designed around real-world programs - the desired Game performance has to arrive as a side effect of accelerating those.

And that is the promise: the next pperl release will smash every interpreted language in the Game, and compete in every single benchmark with the best scripted language there. It will do so not with a specialized JIT tailored to this benchmark code, but with a general-purpose JIT that also happens to smash this game.

As always: no dates. On the other hand you can now quantify the velocity.

  • Richard C. Jelinek, PetaMem s.r.o.

Leave a comment

About PetaMem

user-pic All things Perl.