Commit b7d05db0 authored by Raymond Hettinger's avatar Raymond Hettinger

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%.
parent f0e3569a
...@@ -263,6 +263,9 @@ yellow 5 ...@@ -263,6 +263,9 @@ yellow 5
\begin{itemize} \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 \item The machinery for growing and shrinking lists was optimized
for speed and for space efficiency. Small lists (under eight elements) for speed and for space efficiency. Small lists (under eight elements)
never over-allocate by more than three elements. Large lists do not never over-allocate by more than three elements. Large lists do not
......
...@@ -342,6 +342,7 @@ static PyObject * ...@@ -342,6 +342,7 @@ static PyObject *
list_slice(PyListObject *a, int ilow, int ihigh) list_slice(PyListObject *a, int ilow, int ihigh)
{ {
PyListObject *np; PyListObject *np;
PyObject **src, **dest;
int i, len; int i, len;
if (ilow < 0) if (ilow < 0)
ilow = 0; ilow = 0;
...@@ -356,10 +357,12 @@ list_slice(PyListObject *a, int ilow, int ihigh) ...@@ -356,10 +357,12 @@ list_slice(PyListObject *a, int ilow, int ihigh)
if (np == NULL) if (np == NULL)
return NULL; return NULL;
src = a->ob_item + ilow;
dest = np->ob_item;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
PyObject *v = a->ob_item[i+ilow]; PyObject *v = src[i];
Py_INCREF(v); Py_INCREF(v);
np->ob_item[i] = v; dest[i] = v;
} }
return (PyObject *)np; return (PyObject *)np;
} }
...@@ -646,6 +649,7 @@ listextend_internal(PyListObject *self, PyObject *b) ...@@ -646,6 +649,7 @@ listextend_internal(PyListObject *self, PyObject *b)
register int selflen = PyList_GET_SIZE(self); register int selflen = PyList_GET_SIZE(self);
int blen; int blen;
register int i; register int i;
PyObject **src, **dest;
if (PyObject_Size(b) == 0) { if (PyObject_Size(b) == 0) {
/* short circuit when b is empty */ /* short circuit when b is empty */
...@@ -678,19 +682,17 @@ listextend_internal(PyListObject *self, PyObject *b) ...@@ -678,19 +682,17 @@ listextend_internal(PyListObject *self, PyObject *b)
} }
/* populate the end of self with b's items */ /* populate the end of self with b's items */
if (PyList_Check(b)) { if (PyList_Check(b))
for (i = 0; i < blen; i++) { src = ((PyListObject *)b)->ob_item;
PyObject *o = PyList_GET_ITEM(b, i); else {
Py_INCREF(o);
PyList_SET_ITEM(self, i+selflen, o);
}
} else {
assert (PyTuple_Check(b)); assert (PyTuple_Check(b));
src = ((PyTupleObject *)b)->ob_item;
}
dest = self->ob_item + selflen;
for (i = 0; i < blen; i++) { for (i = 0; i < blen; i++) {
PyObject *o = PyTuple_GET_ITEM(b, i); PyObject *o = src[i];
Py_INCREF(o); Py_INCREF(o);
PyList_SET_ITEM(self, i+selflen, o); dest[i] = o;
}
} }
Py_DECREF(b); Py_DECREF(b);
return 0; return 0;
......
...@@ -306,7 +306,9 @@ static PyObject * ...@@ -306,7 +306,9 @@ static PyObject *
tupleslice(register PyTupleObject *a, register int ilow, register int ihigh) tupleslice(register PyTupleObject *a, register int ilow, register int ihigh)
{ {
register PyTupleObject *np; register PyTupleObject *np;
PyObject **src, **dest;
register int i; register int i;
int len;
if (ilow < 0) if (ilow < 0)
ilow = 0; ilow = 0;
if (ihigh > a->ob_size) if (ihigh > a->ob_size)
...@@ -317,13 +319,16 @@ tupleslice(register PyTupleObject *a, register int ilow, register int ihigh) ...@@ -317,13 +319,16 @@ tupleslice(register PyTupleObject *a, register int ilow, register int ihigh)
Py_INCREF(a); Py_INCREF(a);
return (PyObject *)a; return (PyObject *)a;
} }
np = (PyTupleObject *)PyTuple_New(ihigh - ilow); len = ihigh - ilow;
np = (PyTupleObject *)PyTuple_New(len);
if (np == NULL) if (np == NULL)
return NULL; return NULL;
for (i = ilow; i < ihigh; i++) { src = a->ob_item + ilow;
PyObject *v = a->ob_item[i]; dest = np->ob_item;
for (i = 0; i < len; i++) {
PyObject *v = src[i];
Py_INCREF(v); Py_INCREF(v);
np->ob_item[i - ilow] = v; dest[i] = v;
} }
return (PyObject *)np; return (PyObject *)np;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment