Optimize tuple_slice() and make further improvements to list_slice()
and list.extend(). Factoring the inner loops to remove the constant structure references and fixed offsets gives speedups ranging from 20% to 30%.
This commit is contained in:
parent
f0e3569a28
commit
b7d05db0be
|
@ -263,6 +263,9 @@ yellow 5
|
|||
|
||||
\begin{itemize}
|
||||
|
||||
\item The inner loops for \class{list} and \class{tuple} slicing
|
||||
were optimized and now run about one-third faster.
|
||||
|
||||
\item The machinery for growing and shrinking lists was optimized
|
||||
for speed and for space efficiency. Small lists (under eight elements)
|
||||
never over-allocate by more than three elements. Large lists do not
|
||||
|
|
|
@ -342,6 +342,7 @@ static PyObject *
|
|||
list_slice(PyListObject *a, int ilow, int ihigh)
|
||||
{
|
||||
PyListObject *np;
|
||||
PyObject **src, **dest;
|
||||
int i, len;
|
||||
if (ilow < 0)
|
||||
ilow = 0;
|
||||
|
@ -356,10 +357,12 @@ list_slice(PyListObject *a, int ilow, int ihigh)
|
|||
if (np == NULL)
|
||||
return NULL;
|
||||
|
||||
src = a->ob_item + ilow;
|
||||
dest = np->ob_item;
|
||||
for (i = 0; i < len; i++) {
|
||||
PyObject *v = a->ob_item[i+ilow];
|
||||
PyObject *v = src[i];
|
||||
Py_INCREF(v);
|
||||
np->ob_item[i] = v;
|
||||
dest[i] = v;
|
||||
}
|
||||
return (PyObject *)np;
|
||||
}
|
||||
|
@ -646,6 +649,7 @@ listextend_internal(PyListObject *self, PyObject *b)
|
|||
register int selflen = PyList_GET_SIZE(self);
|
||||
int blen;
|
||||
register int i;
|
||||
PyObject **src, **dest;
|
||||
|
||||
if (PyObject_Size(b) == 0) {
|
||||
/* short circuit when b is empty */
|
||||
|
@ -678,19 +682,17 @@ listextend_internal(PyListObject *self, PyObject *b)
|
|||
}
|
||||
|
||||
/* populate the end of self with b's items */
|
||||
if (PyList_Check(b)) {
|
||||
for (i = 0; i < blen; i++) {
|
||||
PyObject *o = PyList_GET_ITEM(b, i);
|
||||
Py_INCREF(o);
|
||||
PyList_SET_ITEM(self, i+selflen, o);
|
||||
}
|
||||
} else {
|
||||
if (PyList_Check(b))
|
||||
src = ((PyListObject *)b)->ob_item;
|
||||
else {
|
||||
assert (PyTuple_Check(b));
|
||||
for (i = 0; i < blen; i++) {
|
||||
PyObject *o = PyTuple_GET_ITEM(b, i);
|
||||
Py_INCREF(o);
|
||||
PyList_SET_ITEM(self, i+selflen, o);
|
||||
}
|
||||
src = ((PyTupleObject *)b)->ob_item;
|
||||
}
|
||||
dest = self->ob_item + selflen;
|
||||
for (i = 0; i < blen; i++) {
|
||||
PyObject *o = src[i];
|
||||
Py_INCREF(o);
|
||||
dest[i] = o;
|
||||
}
|
||||
Py_DECREF(b);
|
||||
return 0;
|
||||
|
|
|
@ -306,7 +306,9 @@ static PyObject *
|
|||
tupleslice(register PyTupleObject *a, register int ilow, register int ihigh)
|
||||
{
|
||||
register PyTupleObject *np;
|
||||
PyObject **src, **dest;
|
||||
register int i;
|
||||
int len;
|
||||
if (ilow < 0)
|
||||
ilow = 0;
|
||||
if (ihigh > a->ob_size)
|
||||
|
@ -317,13 +319,16 @@ tupleslice(register PyTupleObject *a, register int ilow, register int ihigh)
|
|||
Py_INCREF(a);
|
||||
return (PyObject *)a;
|
||||
}
|
||||
np = (PyTupleObject *)PyTuple_New(ihigh - ilow);
|
||||
len = ihigh - ilow;
|
||||
np = (PyTupleObject *)PyTuple_New(len);
|
||||
if (np == NULL)
|
||||
return NULL;
|
||||
for (i = ilow; i < ihigh; i++) {
|
||||
PyObject *v = a->ob_item[i];
|
||||
src = a->ob_item + ilow;
|
||||
dest = np->ob_item;
|
||||
for (i = 0; i < len; i++) {
|
||||
PyObject *v = src[i];
|
||||
Py_INCREF(v);
|
||||
np->ob_item[i - ilow] = v;
|
||||
dest[i] = v;
|
||||
}
|
||||
return (PyObject *)np;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue