diff options
-rw-r--r-- | Misc/ACKS | 1 | ||||
-rw-r--r-- | Misc/NEWS | 8 | ||||
-rw-r--r-- | Objects/listobject.c | 34 |
3 files changed, 37 insertions, 6 deletions
@@ -62,6 +62,7 @@ Finn Bock Paul Boddie Matthew Boedicker David Bolen +Duncan Booth Jurjen Bos Peter Bosch Eric Bouck @@ -118,6 +118,14 @@ Core and builtins same as split() except that it scans the string from the end working towards the beginning. See SF feature request 801847. +- in a thread on comp.lang.python, several people noted that list() + was much slower than in 2.1 and earlier versions of Python, when used + to create new lists from existing lists. Duncan Booth did some + research that uncovered an optimisation that, for lists below + about 100 elements, was actually slower than the normal case. The + special case criteria have been tightened to rectify the performance + regression. + Extension modules ----------------- diff --git a/Objects/listobject.c b/Objects/listobject.c index 47673be..66e4460 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -2234,6 +2234,13 @@ list_richcompare(PyObject *v, PyObject *w, int op) return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op); } +/* empirically determined threshold for activating an optimisation + * in list_fill() - 100 seems close to optimum for current CPUs and + * compilers, as of December '03. + * see also comment in list_fill(). + */ +#define LISTFILL_OPT_THRESHOLD 100 + /* Adapted from newer code by Tim */ static int list_fill(PyListObject *result, PyObject *v) @@ -2242,14 +2249,29 @@ list_fill(PyListObject *result, PyObject *v) int n; /* guess for result list size */ int i; + /* if source is destination, we're done. */ + if (v == (PyObject *)result) + return 0; + n = result->ob_size; - /* Special-case list(a_list), for speed. */ - if (PyList_Check(v)) { - if (v == (PyObject *)result) - return 0; /* source is destination, we're done */ - return list_ass_slice(result, 0, n, v); - } + /* Special-case list(a_list), for speed: + * - if the source has 0 elements, there's nothing to copy. + * - if the source has more than a threshold number of elements + * slice assignment is a faster way of filling the target + * (the exact threshold is subject to empirical determination). + * Also special case any other zero length sequence, including + * subclasses of list, there being nothing to copy. + */ + if (PyList_CheckExact(v)) { + i = ((PyListObject*)v)->ob_size; + if (i == 0) + return 0; + if (i > LISTFILL_OPT_THRESHOLD) + return list_ass_slice(result, 0, n, v); + } else + if (PySequence_Check(v) && PySequence_Size(v) == 0) + return 0; /* Empty previous contents */ if (n != 0) { |