You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
newSViv() is not used a whole lot by the core. But it is frequently
used in XS modules. In a nutshell, it allocates a new EMPTY SV just to
call sv_setiv which calls sv_upgrade which in turn spends inordinate
amounts of time looking at the properties of the SV to make it an
SVt_IV. But the properties of that SV are always the same: a clean
slate! Therefore, inlining the very simple bits of sv_setiv that are
actually necessary gives a very tangible speed-up.
It's not very easy to benchmark with with a language-level one-liner
because newSViv() isn't too common in the core. Thus follow XS
micro-benchmarks:
Benchmark 1: Virtually no-op XS function.
SV *
echo_integer(int in)
CODE:
RETVAL = newSViv(in);
OUTPUT: RETVAL
$ dumbbench -i50 --pin-frequency -- ./perl -Ilib \
-MXS::APItest -e 'XS::APItest::echo_integer($_) for 1..1000000'
Before: 3.2782e-01 seconds
After: 3.0530e-01 seconds
A small change, but considering the massive overhead of a function call,
quite surprisingly noticeable.
Benchmark 2: XS function that constructs multiple integer values.
SV *
echo_integer_array(int in)
PREINIT:
int i;
AV *av;
CODE:
av = newAV();
RETVAL = newRV_noinc((SV *)av);
av_extend(av, in-1);
for (i = 0; i < in; ++i)
av_store(av, i, newSViv(i));
OUTPUT: RETVAL
$ dumbbench -i50 --pin-frequency -- ./perl -Ilib \
-MXS::APItest -e 'XS::APItest::echo_integer_array(100) for 1..10000'
Before: 1.18363e-01 seconds
After: 0.92050e-01 seconds
While in the grand scheme of things, this might seem like a very small
optimization, there are many XS modules that actually generate a lot of
integer values, de-serializers being good examples.
0 commit comments