diff options
author | Vincent Pit <perl@profvince.com> | 2009-08-27 11:13:09 +0200 |
---|---|---|
committer | Vincent Pit <perl@profvince.com> | 2009-08-27 12:54:36 +0200 |
commit | 16fa5c119c4bda5c0396a5f81296bd1ccc128a9c (patch) | |
tree | ae140159521df8110da72f27f01bb505664cb83c /util.c | |
parent | 04c9e624265a2bf3bdeecd0310e754b5ecc8bbeb (diff) | |
download | perl-16fa5c119c4bda5c0396a5f81296bd1ccc128a9c.tar.gz |
Speed up repeatcpy() by at least 40% for 1-char or numerous repeats
And don't make it receive the interpreter anymore.
For 1-char repeats, use memset(). Otherwise, use the old implementation up
to some (small) length, and then use memcpy() in a binary manner, based on
what we previously copied.
Note that we use memcpy() so both strings shouldn't overlap. The previous
implementation didn't allow this as well. This would be a good place to use
the restrict keyword from C99. I'm not sure if Configure has a probe for it.
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 40 |
1 files changed, 25 insertions, 15 deletions
@@ -3026,26 +3026,36 @@ Perl_my_pclose(pTHX_ PerlIO *ptr) } #endif +#define PERL_REPEATCPY_LINEAR 4 void -Perl_repeatcpy(pTHX_ register char *to, register const char *from, I32 len, register I32 count) +Perl_repeatcpy(register char *to, register const char *from, I32 len, register I32 count) { - register I32 todo; - register const char * const frombase = from; - PERL_UNUSED_CONTEXT; - PERL_ARGS_ASSERT_REPEATCPY; - if (len == 1) { - register const char c = *from; - while (count-- > 0) - *to++ = c; - return; - } - while (count-- > 0) { - for (todo = len; todo > 0; todo--) { - *to++ = *from++; + if (len == 1) + memset(to, *from, count); + else if (count) { + register char *p = to; + I32 items, linear, half; + + linear = count < PERL_REPEATCPY_LINEAR ? count : PERL_REPEATCPY_LINEAR; + for (items = 0; items < linear; ++items) { + register const char *q = from; + I32 todo; + for (todo = len; todo > 0; todo--) + *p++ = *q++; + } + + half = count / 2; + while (items <= half) { + I32 size = items * len; + memcpy(p, to, size); + p += size; + items *= 2; } - from = frombase; + + if (count > items) + memcpy(p, to, (count - items) * len); } } |