summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2003-01-06 10:33:56 +0000
committerRaymond Hettinger <python@rcn.com>2003-01-06 10:33:56 +0000
commit698258a1991db03207353b8403bfff1287ba92cc (patch)
tree99962bd591b20d4f183f70f2b707b3b21aa15969
parent68b539ef9c9f7b4d038185669d486af35ba7ba02 (diff)
downloadcpython-git-698258a1991db03207353b8403bfff1287ba92cc.tar.gz
Optimize string_repeat.
Christian Tismer pointed out the high cost of the loop overhead and function call overhead for 'c' * n where n is large. Accordingly, the new code only makes lg2(n) loops. Interestingly, 'c' * 1000 * 1000 ran a bit faster with old code. At some point, the loop and function call overhead became cheaper than invalidating the cache with lengthy memcpys. But for more typical sizes of n, the new code runs much faster and for larger values of n it runs only a bit slower.
-rw-r--r--Objects/stringobject.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index 748592ea50..acfce8b104 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -933,6 +933,7 @@ static PyObject *
string_repeat(register PyStringObject *a, register int n)
{
register int i;
+ register int j;
register int size;
register PyStringObject *op;
size_t nbytes;
@@ -965,8 +966,16 @@ string_repeat(register PyStringObject *a, register int n)
PyObject_INIT_VAR(op, &PyString_Type, size);
op->ob_shash = -1;
op->ob_sstate = SSTATE_NOT_INTERNED;
- for (i = 0; i < size; i += a->ob_size)
- memcpy(op->ob_sval+i, a->ob_sval, (int) a->ob_size);
+ i = 0;
+ if (i < size) {
+ memcpy(op->ob_sval, a->ob_sval, (int) a->ob_size);
+ i = (int) a->ob_size;
+ }
+ while (i < size) {
+ j = (i <= size-i) ? i : size-i;
+ memcpy(op->ob_sval+i, op->ob_sval, j);
+ i += j;
+ }
op->ob_sval[size] = '\0';
return (PyObject *) op;
}