Skip to content

Commit 2fc4697

Browse files
sir-sigurdzhangyangyu
authored andcommitted
bpo-34151: Improve performance of some list operations (pythonGH-8332)
1 parent 9e84084 commit 2fc4697

2 files changed

Lines changed: 38 additions & 15 deletions

File tree

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Performance of list concatenation, repetition and slicing operations is
2+
slightly improved. Patch by Sergey Fedoseev.

‎Objects/listobject.c‎

Lines changed: 36 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,23 @@ PyList_New(Py_ssize_t size)
180180
return (PyObject *) op;
181181
}
182182

183+
static PyObject *
184+
list_new_prealloc(Py_ssize_t size)
185+
{
186+
PyListObject *op = (PyListObject *) PyList_New(0);
187+
if (size == 0 || op == NULL) {
188+
return (PyObject *) op;
189+
}
190+
assert(op->ob_item == NULL);
191+
op->ob_item = PyMem_New(PyObject *, size);
192+
if (op->ob_item == NULL) {
193+
Py_DECREF(op);
194+
return PyErr_NoMemory();
195+
}
196+
op->allocated = size;
197+
return (PyObject *) op;
198+
}
199+
183200
Py_ssize_t
184201
PyList_Size(PyObject *op)
185202
{
@@ -438,7 +455,7 @@ list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
438455
else if (ihigh > Py_SIZE(a))
439456
ihigh = Py_SIZE(a);
440457
len = ihigh - ilow;
441-
np = (PyListObject *) PyList_New(len);
458+
np = (PyListObject *) list_new_prealloc(len);
442459
if (np == NULL)
443460
return NULL;
444461

@@ -449,6 +466,7 @@ list_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh)
449466
Py_INCREF(v);
450467
dest[i] = v;
451468
}
469+
Py_SIZE(np) = len;
452470
return (PyObject *)np;
453471
}
454472

@@ -479,7 +497,7 @@ list_concat(PyListObject *a, PyObject *bb)
479497
if (Py_SIZE(a) > PY_SSIZE_T_MAX - Py_SIZE(b))
480498
return PyErr_NoMemory();
481499
size = Py_SIZE(a) + Py_SIZE(b);
482-
np = (PyListObject *) PyList_New(size);
500+
np = (PyListObject *) list_new_prealloc(size);
483501
if (np == NULL) {
484502
return NULL;
485503
}
@@ -497,6 +515,7 @@ list_concat(PyListObject *a, PyObject *bb)
497515
Py_INCREF(v);
498516
dest[i] = v;
499517
}
518+
Py_SIZE(np) = size;
500519
return (PyObject *)np;
501520
#undef b
502521
}
@@ -516,28 +535,30 @@ list_repeat(PyListObject *a, Py_ssize_t n)
516535
size = Py_SIZE(a) * n;
517536
if (size == 0)
518537
return PyList_New(0);
519-
np = (PyListObject *) PyList_New(size);
538+
np = (PyListObject *) list_new_prealloc(size);
520539
if (np == NULL)
521540
return NULL;
522541

523-
items = np->ob_item;
524542
if (Py_SIZE(a) == 1) {
543+
items = np->ob_item;
525544
elem = a->ob_item[0];
526545
for (i = 0; i < n; i++) {
527546
items[i] = elem;
528547
Py_INCREF(elem);
529548
}
530-
return (PyObject *) np;
531-
}
532-
p = np->ob_item;
533-
items = a->ob_item;
534-
for (i = 0; i < n; i++) {
535-
for (j = 0; j < Py_SIZE(a); j++) {
536-
*p = items[j];
537-
Py_INCREF(*p);
538-
p++;
549+
}
550+
else {
551+
p = np->ob_item;
552+
items = a->ob_item;
553+
for (i = 0; i < n; i++) {
554+
for (j = 0; j < Py_SIZE(a); j++) {
555+
*p = items[j];
556+
Py_INCREF(*p);
557+
p++;
558+
}
539559
}
540560
}
561+
Py_SIZE(np) = size;
541562
return (PyObject *) np;
542563
}
543564

@@ -2738,7 +2759,7 @@ list_subscript(PyListObject* self, PyObject* item)
27382759
return list_slice(self, start, stop);
27392760
}
27402761
else {
2741-
result = PyList_New(slicelength);
2762+
result = list_new_prealloc(slicelength);
27422763
if (!result) return NULL;
27432764

27442765
src = self->ob_item;
@@ -2749,7 +2770,7 @@ list_subscript(PyListObject* self, PyObject* item)
27492770
Py_INCREF(it);
27502771
dest[i] = it;
27512772
}
2752-
2773+
Py_SIZE(result) = slicelength;
27532774
return result;
27542775
}
27552776
}

0 commit comments

Comments
 (0)