Skip to content

Commit 4846a03

Browse files
committed
Perl_do_print: use S_uiv_2buf for faster IV stringification
`Perl_do_print`'s pre-existing method for stringification of an IV within an SVt_IV involves creating a temporary SVt_PV, using `sv_vcatpvfn_flags` to do the stringification, then freeing the SVt_PV once the buffer has been written out. This is considerably slower than using `S_uiv_2buf`, the helper function used by `sv_2pv_flags`. So this commit modifies `Perl_do_print` to use `sv_2pv_flags`.
1 parent b61ecc7 commit 4846a03

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

doio.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2205,11 +2205,25 @@ Perl_do_print(pTHX_ SV *sv, PerlIO *fp)
22052205
return TRUE;
22062206
if (SvTYPE(sv) == SVt_IV && SvIOK(sv)) {
22072207
assert(!SvGMAGICAL(sv));
2208-
if (SvIsUV(sv))
2209-
PerlIO_printf(fp, "%" UVuf, (UV)SvUVX(sv));
2210-
else
2211-
PerlIO_printf(fp, "%" IVdf, (IV)SvIVX(sv));
2212-
return !PerlIO_error(fp);
2208+
bool happy = TRUE;
2209+
2210+
/* Adapted from Perl_sv_2pv_flags */
2211+
const U32 isUIOK = SvIsUV(sv);
2212+
/* The purpose of this union is to ensure that arr is aligned on
2213+
a 2 byte boundary, because that is what uiv_2buf() requires */
2214+
union {
2215+
char arr[TYPE_CHARS(UV)];
2216+
U16 dummy;
2217+
} buf;
2218+
char *ebuf, *ptr;
2219+
STRLEN len;
2220+
UV tempuv = SvUVX(sv);
2221+
ptr = uiv_2buf(buf.arr, SvIVX(sv), tempuv, isUIOK, &ebuf);
2222+
len = ebuf - ptr;
2223+
2224+
if (len && (PerlIO_write(fp,ptr,len) == 0))
2225+
happy = FALSE;
2226+
return happy ? !PerlIO_error(fp) : FALSE;
22132227
}
22142228
else {
22152229
STRLEN len;

t/perf/benchmarks

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,6 +1938,18 @@
19381938
code => '$p = pos($s);',
19391939
},
19401940

1941+
# func::print::iv_stringify should outperform func::print::iv_strings
1942+
'func::print::iv_stringify' => {
1943+
desc => 'do_print stringification of SVt_IV integers',
1944+
setup => 'open(my $devnull, ">>", "/dev/null") or die $!;',
1945+
code => 'print $devnull 1,2,3,4,5,6,7,8,9,0;',
1946+
},
1947+
'func::print::iv_strings' => {
1948+
desc => 'do_print pre-stringified SVt_IV integers',
1949+
setup => 'open(my $devnull, ">>", "/dev/null") or die $!;',
1950+
code => 'print $devnull "1","2","3","4","5","6","7","8","9","0";',
1951+
},
1952+
19411953
'func::ref::notaref_bool' => {
19421954
desc => 'ref($notaref) in boolean context',
19431955
setup => 'my $r = "boo"',
@@ -1970,8 +1982,6 @@
19701982
code => '$x = ref $r',
19711983
},
19721984

1973-
1974-
19751985
'func::sort::num' => {
19761986
desc => 'plain numeric sort',
19771987
setup => 'my (@a, @b); @a = reverse 1..10;',
@@ -2034,7 +2044,6 @@
20342044
code => '@a = sort f @a',
20352045
},
20362046

2037-
20382047
'func::split::vars' => {
20392048
desc => 'split into two lexical vars',
20402049
setup => 'my $s = "abc:def";',

0 commit comments

Comments
 (0)