summaryrefslogtreecommitdiff
path: root/util.c
diff options
context:
space:
mode:
authorVincent Pit <perl@profvince.com>2009-08-27 11:13:09 +0200
committerVincent Pit <perl@profvince.com>2009-08-27 12:54:36 +0200
commit16fa5c119c4bda5c0396a5f81296bd1ccc128a9c (patch)
treeae140159521df8110da72f27f01bb505664cb83c /util.c
parent04c9e624265a2bf3bdeecd0310e754b5ecc8bbeb (diff)
downloadperl-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.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/util.c b/util.c
index 3f4339318a..ae8c688e2d 100644
--- a/util.c
+++ b/util.c
@@ -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);
}
}