mirror of https://github.com/python/cpython.git
gh-126703: Add freelists for list and tuple iterators (GH-128592)
This commit is contained in:
parent
41ad2bb248
commit
1a80214f11
|
@ -11,6 +11,8 @@ extern "C" {
|
|||
# define PyTuple_MAXSAVESIZE 20 // Largest tuple to save on freelist
|
||||
# define Py_tuple_MAXFREELIST 2000 // Maximum number of tuples of each size to save
|
||||
# define Py_lists_MAXFREELIST 80
|
||||
# define Py_list_iters_MAXFREELIST 10
|
||||
# define Py_tuple_iters_MAXFREELIST 10
|
||||
# define Py_dicts_MAXFREELIST 80
|
||||
# define Py_dictkeys_MAXFREELIST 80
|
||||
# define Py_floats_MAXFREELIST 100
|
||||
|
@ -40,6 +42,8 @@ struct _Py_freelists {
|
|||
struct _Py_freelist ints;
|
||||
struct _Py_freelist tuples[PyTuple_MAXSAVESIZE];
|
||||
struct _Py_freelist lists;
|
||||
struct _Py_freelist list_iters;
|
||||
struct _Py_freelist tuple_iters;
|
||||
struct _Py_freelist dicts;
|
||||
struct _Py_freelist dictkeys;
|
||||
struct _Py_freelist slices;
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Improve performance of iterating over lists and tuples by using a freelist for the iterator objects.
|
|
@ -3903,15 +3903,17 @@ PyTypeObject PyListIter_Type = {
|
|||
static PyObject *
|
||||
list_iter(PyObject *seq)
|
||||
{
|
||||
_PyListIterObject *it;
|
||||
|
||||
if (!PyList_Check(seq)) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
_PyListIterObject *it = _Py_FREELIST_POP(_PyListIterObject, list_iters);
|
||||
if (it == NULL) {
|
||||
it = PyObject_GC_New(_PyListIterObject, &PyListIter_Type);
|
||||
if (it == NULL)
|
||||
if (it == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
it->it_index = 0;
|
||||
it->it_seq = (PyListObject *)Py_NewRef(seq);
|
||||
_PyObject_GC_TRACK(it);
|
||||
|
@ -3924,7 +3926,8 @@ listiter_dealloc(PyObject *self)
|
|||
_PyListIterObject *it = (_PyListIterObject *)self;
|
||||
_PyObject_GC_UNTRACK(it);
|
||||
Py_XDECREF(it->it_seq);
|
||||
PyObject_GC_Del(it);
|
||||
assert(Py_IS_TYPE(self, &PyListIter_Type));
|
||||
_Py_FREELIST_FREE(list_iters, it, PyObject_GC_Del);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -923,6 +923,8 @@ _PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization)
|
|||
clear_freelist(&freelists->tuples[i], is_finalization, free_object);
|
||||
}
|
||||
clear_freelist(&freelists->lists, is_finalization, free_object);
|
||||
clear_freelist(&freelists->list_iters, is_finalization, free_object);
|
||||
clear_freelist(&freelists->tuple_iters, is_finalization, free_object);
|
||||
clear_freelist(&freelists->dicts, is_finalization, free_object);
|
||||
clear_freelist(&freelists->dictkeys, is_finalization, PyMem_Free);
|
||||
clear_freelist(&freelists->slices, is_finalization, free_object);
|
||||
|
|
|
@ -993,7 +993,8 @@ tupleiter_dealloc(PyObject *self)
|
|||
_PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
|
||||
_PyObject_GC_UNTRACK(it);
|
||||
Py_XDECREF(it->it_seq);
|
||||
PyObject_GC_Del(it);
|
||||
assert(Py_IS_TYPE(self, &PyTupleIter_Type));
|
||||
_Py_FREELIST_FREE(tuple_iters, it, PyObject_GC_Del);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1119,15 +1120,16 @@ PyTypeObject PyTupleIter_Type = {
|
|||
static PyObject *
|
||||
tuple_iter(PyObject *seq)
|
||||
{
|
||||
_PyTupleIterObject *it;
|
||||
|
||||
if (!PyTuple_Check(seq)) {
|
||||
PyErr_BadInternalCall();
|
||||
return NULL;
|
||||
}
|
||||
_PyTupleIterObject *it = _Py_FREELIST_POP(_PyTupleIterObject, tuple_iters);
|
||||
if (it == NULL) {
|
||||
it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type);
|
||||
if (it == NULL)
|
||||
return NULL;
|
||||
}
|
||||
it->it_index = 0;
|
||||
it->it_seq = (PyTupleObject *)Py_NewRef(seq);
|
||||
_PyObject_GC_TRACK(it);
|
||||
|
|
Loading…
Reference in New Issue