A new release of Rakudo was just announced. Most of the changes increase Perl 6 performance this time. Let us briefly look at some of them.
I am happy to tell that my blog initiated at least two of the changes.
Removed UInt64 (not to be confused with uint64) [cf154355]
We’ve seen this class in the post about native integers. The UInt64 type remained in the codebase for a long time while it was not actually used. The uint type, though, is still to-be-used as the type of the denominator in Rats:
# XXX: should be Rational[Int, uint] my class Rat is Cool does Rational[Int, Int] {
Made DateTime creation about 1.6x faster [36d71a39]
As we saw, the DateTime constructor used the in-range method, which was replaced with faster explicit tests:
- (1..12).in-range($month,'Month'); - (1 .. self.DAYS-IN-MONTH($year,$month)).in-range($day,'Day'); - (0..23).in-range($hour,'Hour'); - (0..59).in-range($minute,'Minute'); + 1 <= $month <= 12 + || X::OutOfRange.new(:what<Month>,:got($month),:range<1..12>).throw; + 1 <= $day <= self.DAYS-IN-MONTH($year,$month) + || X::OutOfRange.new( + :what<Day>, + :got($day), + :range("1..{self.DAYS-IN-MONTH($year,$month)}") + ).throw; + 0 <= $hour <= 23 + || X::OutOfRange.new(:what<Hour>,:got($hour),:range<0..23>).throw; + 0 <= $minute <= 59 + || X::OutOfRange.new(:what<Minute>,:got($minute),:range<0..59>).throw;
Made adding integers to Rats 22% faster [418fc068]
Creating Rats is an interesting procedure, which I am going to blog about in the future. For now, let me show the changes from this commit:
sub DON'T_DIVIDE_NUMBERS(Int:D \nu, Int:D \de, $t1, $t2) { - my $r; - if nqp::istype($t1, FatRat) || nqp::istype($t2, FatRat) { - $r := nqp::create(FatRat); - nqp::bindattr($r, FatRat, '$!numerator', nqp::decont(nu)); - nqp::bindattr($r, FatRat, '$!denominator', nqp::decont(de)); - } else { - $r := nqp::create(Rat); - nqp::bindattr($r, Rat, '$!numerator', nqp::decont(nu)); - nqp::bindattr($r, Rat, '$!denominator', nqp::decont(de)); - } - $r; + nqp::istype($t1, FatRat) || nqp::istype($t2, FatRat) + ?? nqp::p6bindattrinvres( + nqp::p6bindattrinvres( + nqp::create(FatRat), + FatRat, '$!numerator', nqp::decont(nu)), + FatRat, '$!denominator', nqp::decont(de)) + !! nqp::p6bindattrinvres( + nqp::p6bindattrinvres( + nqp::create(Rat), + Rat, '$!numerator', nqp::decont(nu)), + Rat, '$!denominator', nqp::decont(de))
This is a routine that is a part of creating a Rat value from two integers. A Rat value internally contains two attributes, the numerator and the denominator. They were bound via the nqp::bindattr method with the help of some temporary variable. Now the Rakudo’s nqp::p6bindattrinvres method is used directly. This method is equivalent to the following code (see docs/ops.markdown in the Rakudo directory):
{ bindattr($obj, $type, $attr-name, $value); $obj; }
Made use of faster typechecks (7.5x faster) [4c9b84f8][8f71b0e0][10cd405f]
The key idea of this change is to replace the Perl 6 type checks with NQP ones, all changes are in src/Perl6/Actions.nqp, for example:
- if $past.isa(QAST::Var) { + if nqp::istype($past, QAST::Var) { - if $elem ~~ QAST::Op + if nqp::istype($elem, QAST::Op)
As a useful exercise, you can trace back the behaviour of both .isa and ~~ in the code and see why it could slow down the check.
Made operator chains up to 2.4x faster [b77d8756]
The change was made in src/Perl6/Optimizer.nqp, and we are not going to read it here, but I wanted to mention this change because it is relevant to a small but very handy feature of Perl 6, chain comparisons such as 1 < $x < 2. It is claimed that now it works almost as fast as 1 < $x && $x < 2.
Made .sum on 2-element Lists about 30% faster [0af3f4d1]
This is an interesting change in the code that, basically, avoids using a loop for adding up two values:
- nqp::stmts( - (my $list := $!reified), - (my $sum = nqp::ifnull(nqp::atpos($list,0),0)), - (my int $i), - nqp::while( - nqp::islt_i($i = nqp::add_i($i,1),$elems), - ($sum = $sum + nqp::ifnull(nqp::atpos($list,$i),0)) + nqp::if( + nqp::isgt_i($elems,2), + nqp::stmts( + (my $list := $!reified), + (my $sum = nqp::ifnull(nqp::atpos($list,0),0)), + (my int $i), + nqp::while( + nqp::islt_i($i = nqp::add_i($i,1),$elems), + ($sum = $sum + nqp::ifnull(nqp::atpos($list,$i),0)) + ), + $sum
A lot of NQP code here in src/core/List.pm, but you can understand it if I tell you that nqp::stmts makes a sequence of statements a single statement. Thus, the nqp::isgt_i check has two branches: for arrays that either have one or two, or arrays with more elements.
There are more interesting changes but most of them require deeper understanding of Rakudo.
2 thoughts on “🔬36. Rakudo 2018.01”