Faster.pm の最適化
Faster.pm がやってることは、基本的には Perl VM がやってる処理を C のコードにかきくだしただけなのです。生成されてる C のコードは以下のようなかんじだ。
ここからさらに最適化できれば、ぐっと速くできるのだけど。
#define PERL_NO_GET_CONTEXT #define PERL_CORE #include <assert.h> #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #if 1 # define faster_PUSHMARK_PREALLOC(count) while (PL_markstack_ptr + (count) >= PL_ markstack_max) markstack_grow () # define faster_PUSHMARK(p) *++PL_markstack_ptr = (p) - PL_stack_base #else # define faster_PUSHMARK_PREALLOC(count) 1 # define faster_PUSHMARK(p) PUSHMARK(p) #endif #define RUNOPS_TILL(op) \ while (nextop != (op)) \ { \ PERL_ASYNC_CHECK (); \ PL_op = nextop; nextop = (PL_op->op_ppaddr)(aTHX); \ } OP *F485e855f8965caa3b40498ee2da71dcc (pTHX) { register OP *nextop = (OP *)34431168L; faster_PUSHMARK_PREALLOC (1); op_34431168: /* nextstate */ PL_curcop = (COP *)nextop; PL_stack_sp = PL_stack_base + cxstack[cxstack_ix].blk_oldsp; FREETMPS; nextop = (OP *)34430960L; goto op_34430960; op_34430960: /* pushmark */ faster_PUSHMARK (PL_stack_sp); nextop = (OP *)34431264L; goto op_34431264; op_34431264: /* aelemfast */ { dSP; EXTEND (SP, 3); PUTBACK; } { AV *av = GvAV ((GV *)34279824L); SV **svp = av_fetch (av, 0, 0); SV *sv = svp ? *svp : &PL_sv_undef; if (SvGMAGICAL (sv)) sv = sv_mortalcopy (sv); dSP; PUSHs (sv); PUTBACK; } nextop = (OP *)34431424L; goto op_34431424; op_34431424: /* const */ { dSP; PUSHs ((SV *)34392504L); PUTBACK; } nextop = (OP *)34430720L; goto op_34430720; op_34430720: /* add */ PL_op = nextop; nextop = Perl_pp_add (aTHX); goto op_34431760; op_34431760: /* const */ { dSP; PUSHs ((SV *)34280232L); PUTBACK; } nextop = (OP *)34431040L; goto op_34431040; op_34431040: /* print */ PERL_ASYNC_CHECK (); PL_op = nextop; nextop = Perl_pp_print (aTHX); goto op_34432192; op_34432192: /* leavesub */ PERL_ASYNC_CHECK (); return nextop; op_0: return 0; }