PERL_NO_GET_CONTEXT

XSモジュールを書くときはPERL_NO_GET_CONTEXTを試してみるといいようだ。
perlgutsによれば,perlのビルド時にPERL_IMPLICIT_CONTEXTが指定されているとき,PERL_NO_GET_CONTEXTマクロをperlヘッダの#includeの前に定義すると効率がよくなる,とある。この動作がデフォルトでないのはithread実装以前のPerlとの互換性のためとあるので,最近のXSモジュールならば常にPERL_NO_GET_CONTEXTを定義してもよさそうである*1
そしてPERL_NO_GET_CONTEXTにより,PerlAPIへのアクセスが劇的に速くなる。たとえば,Acme::StringFormatで試してみると,PERL_NO_GET_CONTEXTを定義するだけで5倍ほど高速になった。

PERL_NO_GET_CONTEXTなし(デフォルト):

$ perl example/benchmark.pl
number of arguments: 1
Benchmark: running %, sprintf for at least 1 CPU seconds...
         %:  1 wallclock secs ( 1.05 usr +  0.00 sys =  1.05 CPU) @ 136533.33/s
(n=143360)
   sprintf:  1 wallclock secs ( 1.08 usr +  0.00 sys =  1.08 CPU) @ 799971.35/s
(n=865569)
            Rate       % sprintf
%       136533/s      --    -83%
sprintf 799971/s    486%      --

PERL_NO_GET_CONTEXTあり:

$ perl -Mblib example/benchmark.pl
number of arguments: 1
Benchmark: running %, sprintf for at least 1 CPU seconds...
         %:  0 wallclock secs ( 1.06 usr +  0.00 sys =  1.06 CPU) @ 616518.34/s
(n=655359)
   sprintf:  2 wallclock secs ( 1.07 usr +  0.00 sys =  1.07 CPU) @ 803136.32/s
(n=860159)
            Rate       % sprintf
%       616518/s      --    -23%
sprintf 803136/s     30%      --

もっともこれは極端な例で,通常はここまで劇的に改善することはないようだが。

See Also perlguts / How multiple interpreters and concurrency are supported.

*1:ppport.hを導入すれば,5.005以前のPerlと互換性を保つこともできるようだ