diff options
author | Eric Herman <eric@freesa.org> | 2014-11-28 15:08:04 +0100 |
---|---|---|
committer | Steffen Mueller <smueller@cpan.org> | 2014-11-28 15:45:47 +0100 |
commit | bd30fe8921c88e4677c2279b442a56a11ae037b4 (patch) | |
tree | f5a7044e46aecfb36e954c98e1e5aef293c11928 /sv.c | |
parent | de06ff5a50f29eaee3e72394fa1c2417689cac47 (diff) | |
download | perl-bd30fe8921c88e4677c2279b442a56a11ae037b4.tar.gz |
Speed up newSViv()
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.
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 17 |
1 files changed, 16 insertions, 1 deletions
@@ -9359,7 +9359,22 @@ Perl_newSViv(pTHX_ const IV i) SV *sv; new_SV(sv); - sv_setiv(sv,i); + + /* Inlining ONLY the small relevant subset of sv_setiv here + * for performance. Makes a significant difference. */ + + /* We're starting from SVt_FIRST, so provided that's + * actual 0, we don't have to unset any SV type flags + * to promote to SVt_IV. */ + assert(SVt_FIRST == 0); + + SET_SVANY_FOR_BODYLESS_IV(sv); + SvFLAGS(sv) |= SVt_IV; + (void)SvIOK_on(sv); + + SvIV_set(sv, i); + SvTAINT(sv); + return sv; } |