Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Elizabeth Mattijsen
Elizabeth Mattijsen

Posted on

     

Moving printf formats forward

One of the advantages ofRakuAST is that you can build executable code in an object oriented style. One of the areas that has had the attention of yours truly in that respect, is handling ofsprintf formats.

Historically the C programming language provided the first implementation ofprintf logic:

The printf family of functions in the C programming language are a set of functions that take a format string as input among a variable sized list of other values and produce as output a string that corresponds to the format specifier and given input values.

And in Raku?

Of course, the Raku Programming Language also has an implementation ofprintf, with a set ofsupported options. However the Rakudo implementation of the Raku Programming Language does not have an implementation ofprintf formats of its own, but borrows it fromNQP. Which has its pros and its cons.

The pros are of course being that NQP in general is much faster than Raku (as NQP is sort of the"assembly language" of Rakudo). However, the NQP implementation ofsprintf is written using a grammar (written in NQP). Andeach time a call is made to thissprintf functionality (e.g, when printing a line in a report usingsprintf), the whole grammar is run again, with the associated actions building the string to be returned. And running a grammar is costly in terms of memoryand CPU.

This makes Rakudo'ssprintf and associated functions (such as.fmt) one of the slowest features of Raku in Rakudo. Surely with RakuAST there must be a better way to do this?

Enter Formatter

Almost two years ago, yours truly started on the RakuAST journey. First by writing tests, later trying out RakuAST features. And one of the first things attempted, was to port the original NQP grammar forsprintf to Raku. And create a separate set of actions, that wouldnot produce a string, but instead would produce anAST.

Such an AST can then be converted to executable code, and then run whenever a set of arguments would need to be converted to a string. So instead of needing to run the same grammar over and over again, it would be possible to just call some (static) code, which then, like any other piece of code in Raku, would get run-time optimized for better performance.

This then became theFormatter class. And since this was a completely new feature, it only became available for use by opting into the6.e.PREVIEW language version. And then it went largely unnoticed and uncared for the next 1.5 year. As clearly the time wasn't right for it yet.

Obstacles

One of the obstacles that was encountered while working onFormatter, was that there wereno comprehensive tests forsprintf functionality for Raku. Yes, there wasa test-file that tested some features, but no comprehensive tests for all possible combinations of format features, combined with possible values that they should operate upon.

This became one of the first things that needed to be done, to be able to say the new implementation would be matching the old. During the development ofthese tests, it became clear there were some inconsistencies in the existing implementation, and worse:outright bugs.

So the question became: should the new implementation follow the behaviour of the old implementation to the letter, or not?

Raku Core Summit

This then became part of discussions at the firstRaku Core Summit. There it was decided that the new implementation should not adhere to the old one, because the newsprintf functionality would require a language version bump anyway. And that the currentsprintf tests should be frozen for language level6.d. And so it wasdone.

Another decision that was made, was that the functionality offered by theFormatter class (which converts a format string to aCallable), should be embedded into aFormat class. Which should normally act as a string, but when used as aCallable should perform the processing according to the format given. This has now also beenimplemented. Which means you can now do:

use v6.e.PREVIEW;my $f = Format.new("%5s");dd $f;              # Format.new("%5s")say $f;             # %5sdd $f("foo");       # "  foo"say "'$f'";         # '%5s'say "'$f("foo")'";  # '  foo'
Enter fullscreen modeExit fullscreen mode

As you can see, theFormat object acts very much so as a string. Which isn't so strange when you realize the method resolution order ofFormat:

use v6.e.PREVIEW;say Format.^mro;  # ((Format) (Str) (Cool) (Any) (Mu))
Enter fullscreen modeExit fullscreen mode

Only when used as aCallable (by putting() after it with arguments), will it show its special functionality.

A new quote adverb

At the RCS it was suggested that theFormat.new("%5s") would be too clunky in common usage. More seriously it would prevent compile time creation of theFormat object because the lookup of methods are a runtime action in Raku (generally). A way to get around that, would be to introduce a new string quoting construct / adverb / processor. Thisbecame the"format" adverb (or"o" for the short version):

use v6.e.PREVIEW;  # RAKUDO_RAKUAST=1 also required for nowmy $format = q:format/%5s/;say "'$format("foo")'";   # '  foo'
Enter fullscreen modeExit fullscreen mode

or more directly and shorter using the "o" alternate adverb:

use v6.e.PREVIEW;dd q:o/%5s/("foo");  # "  foo"
Enter fullscreen modeExit fullscreen mode

Why"o" for the short version? Because"f" was already taken to enable/disable *f*unction interpolation. Andq:o felt visually closer tofo than anything else.

Performance

So what is the performance of this new way of formatting values into a string?

Without any optimization of the RakuAST version yet, upto a 30x speed increase has been reported. So that's quite an improvement. And potentially better than many other programming languages that also depend on some kind of runtime state-machine to create the string, rather than depending on executable code.

Conclusion

A new way of creating strings from a given set of values and format string (in other wordsprintf functionality) has been implemented using RakuAST in the Raku Programming Language, making it up to 30x as fast.

This functionality will be available from release 2023.06 of Rakudo and selecting the6.e language level by specifyinguse v6.e.PREVIEW. The new quote adverb will for now only be available when compiled with the new RakuAST grammar, which can be activated by specifying theRAKUDO_RAKUAST environment variable.

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

Mostly working on the Raku Programming Language. Born at 314 ppm.
  • Location
    Echt, NL
  • Joined

More fromElizabeth Mattijsen

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp