mutsu と nqp を多用したライブラリ
https://github.com/timo/json_fast
JSON::Fast は rakudo の toolchain でも採用されているライブラリであって、Raku においては重要な意味をもつモジュールだ。 このライブラリは nqp 命令を多様することにより、素の raku に比べて極めて高速化されている。
https://tokuhirom.github.io/mutsu/bench-trend.html
通常の micro benchmark では概ね mutsu のほうが高速になっているのが実態である。これは、Cranelift を用いた JIT などの効果が大きい。
一方で、nqp 命令を多様するケースのみ劣後している。
たとえば、JSON::Fast では以下のようなスタイルでコードが書かれている。
sub str-escape(\text) {
my $codes := text.NFD;
my int $i = -1;
nqp::while(
nqp::islt_i(++$i,nqp::elems($codes)),
nqp::if(
nqp::isle_i((my int $code = nqp::atpos_i($codes,$i)),92)
|| nqp::isge_i($code,128),
nqp::if( # not ascii
nqp::isle_i($code,31),
nqp::if( # control
nqp::iseq_i($code,10),
nqp::splice($codes,$lf,$i++,1), # \n
nqp::if(
nqp::iseq_i($code,13),
nqp::splice($codes,$cr,$i++,1), # \r
nqp::if(
nqp::iseq_i($code,9),
nqp::splice($codes,$tab,$i++,1), # \t
nqp::stmts( # other control
nqp::splice($codes,$code.fmt(Q/\u%04x/).NFD,$i,1),
($i = nqp::add_i($i,5))
)
)
)
),
nqp::if( # not control
nqp::iseq_i($code,34),
nqp::splice($codes,$qq,$i++,1), # "
nqp::if(
nqp::iseq_i($code,92),
nqp::splice($codes,$bs,$i++,1), # \
nqp::if(
nqp::isge_i($code,0x10000),
nqp::stmts( # surrogates
nqp::splice(
$codes,
(my $surrogate := to-surrogate-pair($code.chr).NFD),
$i,
1
),
($i = nqp::sub_i(nqp::add_i($i,nqp::elems($surrogate)),1))
)
)
)
)
)
)
);
nqp::strfromcodes($codes)
}
これはなんというか、MoarVM の命令を手書きしているに等しい。add_i などの命令は、integer の加算命令として MoarVM の IR を直接よぶコードにコンパイルされる。 一方で、mutsu ではこれを関数コールとして実装していた。
それではあまりに差が大きすぎるので、nqp:: の命令を、直接 Ir として扱うような最適化を入れざるをえないかなぁ、と思っている。
Published: 2026-09-20(Sun) 06:28