From b7d05db0beacb9f24300d5fa26b14c3f73d6c622 Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 8 Mar 2004 07:25:05 +0000 Subject: [PATCH] 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%. --- Doc/whatsnew/whatsnew24.tex | 3 +++ Objects/listobject.c | 30 ++++++++++++++++-------------- Objects/tupleobject.c | 13 +++++++++---- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/Doc/whatsnew/whatsnew24.tex b/Doc/whatsnew/whatsnew24.tex index 2a323ff84e0..1607cc78fac 100644 --- a/Doc/whatsnew/whatsnew24.tex +++ b/Doc/whatsnew/whatsnew24.tex @@ -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 diff --git a/Objects/listobject.c b/Objects/listobject.c index 0508d37b006..f5a9c7b087c 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -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; diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c index ef5cb8518b3..eaf3c88b1d4 100644 --- a/Objects/tupleobject.c +++ b/Objects/tupleobject.c @@ -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; }