This week pleases me greatly, because there’s performance improvements to report!

Startup time & performance

lizmat worked hard to make initialization of the module installation database in rakudo lazy, so that any script that doesn’t “use” any module won’t take the performance hit. This (together with a bunch of other improvements) gets startup time (as measured by compiling and running an empty program) back to 0.17s on my machine (previously it was 0.31s) and the memory usage went from about 85 megs to 69 megs (these numbers come from the time command outputting the maximum resident set size). On lizmat’s machine, that reduced the time it took to do a full spectest run from 1620 to 1435 CPU seconds.

On the other side of the module installation database coin, froggs and jnthn just had a little breakthrough that will finally allow the json database to be replaced with a MoarVM serialization blob. Needless to say, this will be a whole bunch faster to load and store when we actually do need to load the database.

On top of these big improvements there’s of course been small improvements again. After profiling found out that a lot of time is spent decoding utf8 during startup, jnthn switched a bunch of things that are known to always be valid latin1 to decode that instead. This reduces the instructions run during startup by about 10%.

Another nice change is that .moarvm files used to contain not only a string heap section but also a chunk of code that used to create a list of all these strings. Now the string heap is used for both purposes, shaving a good 60 kilobytes off the CORE.setting.moarvm (still about 9 megabytes big) and reducing the startup time by about 2%. And then there’s a few sundry changes that all shave off a few percent here and there.

Adding to this heap of performance improvements all around, hashes on MoarVM no longer preserve insertion order. This feature – which users were discouraged from relying on anyway – was implemented in uthash by a doubly-linked list. jnthn removed that doubly linked list and made hashes save a noticable bit of memory: 16 bytes per hash entry and another 8 bytes per hash.

In the future, uthash will be more heavily modified so that strings representing the same text in different storage formats (8 byte per character vs full NFG) will result in the same hash. Then we’ll finally be able to store simpler strings more compactly. I’ve been looking forward to this for a long time, and now it seems to be within reach 🙂

Something I forgot to mention last week is that a whole bunch of methods on Str are now much faster because they have gotten their own implementation rather than relying on Cool to implement them (and do a needless coercion first in every case). This change was inspired by making .chars much faster in the very same way.

Bug Fixes

There used to be a bug where you’d get maddening errors like this:

Calling rl_get_screen_size(TypedPointer[Int], TypedPointer[Int]) will never work with declared signature (TypedPointer[Int], TypedPointer[Int])

This came from NativeCall using the “make_pun” meta-object method that erroneously created a fresh, distinct class each time TypedPointer[Something] was used somewhere. That method call has now been replaced with just “pun”, which goes through a cache first.

ptc found and fixed a few small memory leaks in MoarVM.

Today jnthn spent time on known multithreading-related instabilities and oddnesses. A big part of that was fixing a race in the Fixed Size Allocator which is used for frames, on-stack-replacement, stuff like that. There was a CAS-based lock that suffered from an ABA problem, which basically means one thread interpreted “two changes” (there and back) as “no change” (“go ahead”) and the list of free spots in the allocation pool could get corrupted, leading to memory corruption in objects when two threads use the same spot for different types of objects. The multi dispatch cache also just got a lock added to it, too. There is still more waiting to be found and fixed, though.

I personally got a tiny bit of work in, as well: If you ever encountered the error “Can’t adverb that!”, you’ll now find that it’ll also give a little hint as to what exactly the parser thought you were trying to adverb (because the precedence level of adverbs takes a little getting used to, IMO).

There used to be a problem related to statement modifiers and the given and for keywords where the value of $_ would get messed up, and block-less “gather” sometimes didn’t work where just adding curly braces would fix the problem. Thanks to jnthn, that’s fixed now as well.

Implemented features

Thanks to lizmat variables can now take “will” blocks, which correspond to phasers. Those already implemented are enter, leave, keep, undo, first, next, last, pre and end. Also, unimplemented “will” types now throw an error instead of failing silently. In addition to that, “lazy attributes” are now supported in rakudo. These let you write code like this:

class Example { has $.attr will lazy { # do some expensive set-up here "hello" # value returned from this block will be used } }

When the attr is first accessed, it will run the code to set up the value and after that it will behave like any regular attribute.

After making List.roll faster last week, lizmat also made List.roll(*) (and List.roll(Inf)) return a list that knows it’s infinite.

If you set the environment variable RAKUDO_VERBOSE_STACKFRAME to a number, that number of lines of code around a line indicated in a stack trace will be shown. Another change to stack traces is that instead of a few select routines from the core setting, all routines in the core setting will now be hidden from backtraces by default – you can get full backtraces with the –ll-exception flag as before.

Even though this isn’t strictly a feature, there’s also been more changes regarding the GLR – mostly how flattening and nonflattening happens in relation to “for” and “map” in both their sub and method form. Lists and Parcel have been moving closer and closer and soon the Parcel class will be thrown out.

Ecosystem goodness and documentation

Even though recent changes to the module installation system and making hashes unordered brought a few bugs and problems out of hiding, there’s more nice stuff to be found in the ecosystem now!

Module::Minter gets your own module started with the basic files every such project needs (by dnmfarrell)

Template::Protone lets you write templates that compile down to fast perl6 subs and let you easily embed perl6 code (by tony-o)

ANTLR4::Grammar lets you parse an ANTLR4 grammar and use it to parse stuff. (Though it’s not been put into the ecosystem yet, I decided to highlight it here none the less.) (by DrForr)

ptc has pushed a whole bunch of commits to the perl6 examples site and ptc, stmuk, jonathanstowe and moritz have been adding and modifying more and more stuff on the perl6 documentation site.

labster wrote a blog post “Three Tales of Second System Syndrome” that he put up on his site, hoping to get a bit of feedback before spreading it further. However, it reached Hacker News only shortly after he went to bed and there’s now 121 comments in the corresponding thread.

That’s it for today!

Very strange; even though it feels like I’ve written the longest post in a few weeks, I also have a sneaking suspicion that I’ve forgotten to mention multiple things!

In any case, it’s time for me to finally finish up and maybe get back to annotating MoarVM’s code with a few hints for Valgrind and its tools. Have a great week!