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 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_tuple_MAXFREELIST 2000 // Maximum number of tuples of each size to save
|
||||||
# define Py_lists_MAXFREELIST 80
|
# define Py_lists_MAXFREELIST 80
|
||||||
|
# define Py_list_iters_MAXFREELIST 10
|
||||||
|
# define Py_tuple_iters_MAXFREELIST 10
|
||||||
# define Py_dicts_MAXFREELIST 80
|
# define Py_dicts_MAXFREELIST 80
|
||||||
# define Py_dictkeys_MAXFREELIST 80
|
# define Py_dictkeys_MAXFREELIST 80
|
||||||
# define Py_floats_MAXFREELIST 100
|
# define Py_floats_MAXFREELIST 100
|
||||||
|
@ -40,6 +42,8 @@ struct _Py_freelists {
|
||||||
struct _Py_freelist ints;
|
struct _Py_freelist ints;
|
||||||
struct _Py_freelist tuples[PyTuple_MAXSAVESIZE];
|
struct _Py_freelist tuples[PyTuple_MAXSAVESIZE];
|
||||||
struct _Py_freelist lists;
|
struct _Py_freelist lists;
|
||||||
|
struct _Py_freelist list_iters;
|
||||||
|
struct _Py_freelist tuple_iters;
|
||||||
struct _Py_freelist dicts;
|
struct _Py_freelist dicts;
|
||||||
struct _Py_freelist dictkeys;
|
struct _Py_freelist dictkeys;
|
||||||
struct _Py_freelist slices;
|
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 *
|
static PyObject *
|
||||||
list_iter(PyObject *seq)
|
list_iter(PyObject *seq)
|
||||||
{
|
{
|
||||||
_PyListIterObject *it;
|
|
||||||
|
|
||||||
if (!PyList_Check(seq)) {
|
if (!PyList_Check(seq)) {
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
it = PyObject_GC_New(_PyListIterObject, &PyListIter_Type);
|
_PyListIterObject *it = _Py_FREELIST_POP(_PyListIterObject, list_iters);
|
||||||
if (it == NULL)
|
if (it == NULL) {
|
||||||
return NULL;
|
it = PyObject_GC_New(_PyListIterObject, &PyListIter_Type);
|
||||||
|
if (it == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
it->it_index = 0;
|
it->it_index = 0;
|
||||||
it->it_seq = (PyListObject *)Py_NewRef(seq);
|
it->it_seq = (PyListObject *)Py_NewRef(seq);
|
||||||
_PyObject_GC_TRACK(it);
|
_PyObject_GC_TRACK(it);
|
||||||
|
@ -3924,7 +3926,8 @@ listiter_dealloc(PyObject *self)
|
||||||
_PyListIterObject *it = (_PyListIterObject *)self;
|
_PyListIterObject *it = (_PyListIterObject *)self;
|
||||||
_PyObject_GC_UNTRACK(it);
|
_PyObject_GC_UNTRACK(it);
|
||||||
Py_XDECREF(it->it_seq);
|
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
|
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->tuples[i], is_finalization, free_object);
|
||||||
}
|
}
|
||||||
clear_freelist(&freelists->lists, 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->dicts, is_finalization, free_object);
|
||||||
clear_freelist(&freelists->dictkeys, is_finalization, PyMem_Free);
|
clear_freelist(&freelists->dictkeys, is_finalization, PyMem_Free);
|
||||||
clear_freelist(&freelists->slices, is_finalization, free_object);
|
clear_freelist(&freelists->slices, is_finalization, free_object);
|
||||||
|
|
|
@ -993,7 +993,8 @@ tupleiter_dealloc(PyObject *self)
|
||||||
_PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
|
_PyTupleIterObject *it = _PyTupleIterObject_CAST(self);
|
||||||
_PyObject_GC_UNTRACK(it);
|
_PyObject_GC_UNTRACK(it);
|
||||||
Py_XDECREF(it->it_seq);
|
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
|
static int
|
||||||
|
@ -1119,15 +1120,16 @@ PyTypeObject PyTupleIter_Type = {
|
||||||
static PyObject *
|
static PyObject *
|
||||||
tuple_iter(PyObject *seq)
|
tuple_iter(PyObject *seq)
|
||||||
{
|
{
|
||||||
_PyTupleIterObject *it;
|
|
||||||
|
|
||||||
if (!PyTuple_Check(seq)) {
|
if (!PyTuple_Check(seq)) {
|
||||||
PyErr_BadInternalCall();
|
PyErr_BadInternalCall();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type);
|
_PyTupleIterObject *it = _Py_FREELIST_POP(_PyTupleIterObject, tuple_iters);
|
||||||
if (it == NULL)
|
if (it == NULL) {
|
||||||
return NULL;
|
it = PyObject_GC_New(_PyTupleIterObject, &PyTupleIter_Type);
|
||||||
|
if (it == NULL)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
it->it_index = 0;
|
it->it_index = 0;
|
||||||
it->it_seq = (PyTupleObject *)Py_NewRef(seq);
|
it->it_seq = (PyTupleObject *)Py_NewRef(seq);
|
||||||
_PyObject_GC_TRACK(it);
|
_PyObject_GC_TRACK(it);
|
||||||
|
|
Loading…
Reference in New Issue