mirror of
https://github.com/python/cpython.git
synced 2025-07-07 19:35:27 +00:00
gh-126703: Add freelist for range and range_iter objects (GH-128619)
This commit is contained in:
parent
2067378e6d
commit
dff8bcfa3c
4 changed files with 30 additions and 9 deletions
|
@ -18,6 +18,8 @@ extern "C" {
|
||||||
# define Py_floats_MAXFREELIST 100
|
# define Py_floats_MAXFREELIST 100
|
||||||
# define Py_ints_MAXFREELIST 100
|
# define Py_ints_MAXFREELIST 100
|
||||||
# define Py_slices_MAXFREELIST 1
|
# define Py_slices_MAXFREELIST 1
|
||||||
|
# define Py_ranges_MAXFREELIST 6
|
||||||
|
# define Py_range_iters_MAXFREELIST 6
|
||||||
# define Py_contexts_MAXFREELIST 255
|
# define Py_contexts_MAXFREELIST 255
|
||||||
# define Py_async_gens_MAXFREELIST 80
|
# define Py_async_gens_MAXFREELIST 80
|
||||||
# define Py_async_gen_asends_MAXFREELIST 80
|
# define Py_async_gen_asends_MAXFREELIST 80
|
||||||
|
@ -49,6 +51,8 @@ struct _Py_freelists {
|
||||||
struct _Py_freelist dicts;
|
struct _Py_freelist dicts;
|
||||||
struct _Py_freelist dictkeys;
|
struct _Py_freelist dictkeys;
|
||||||
struct _Py_freelist slices;
|
struct _Py_freelist slices;
|
||||||
|
struct _Py_freelist ranges;
|
||||||
|
struct _Py_freelist range_iters;
|
||||||
struct _Py_freelist contexts;
|
struct _Py_freelist contexts;
|
||||||
struct _Py_freelist async_gens;
|
struct _Py_freelist async_gens;
|
||||||
struct _Py_freelist async_gen_asends;
|
struct _Py_freelist async_gen_asends;
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Improve performance of :class:`range` by using a freelist.
|
|
@ -931,6 +931,8 @@ _PyObject_ClearFreeLists(struct _Py_freelists *freelists, int is_finalization)
|
||||||
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);
|
||||||
|
clear_freelist(&freelists->ranges, is_finalization, free_object);
|
||||||
|
clear_freelist(&freelists->range_iters, is_finalization, free_object);
|
||||||
clear_freelist(&freelists->contexts, is_finalization, free_object);
|
clear_freelist(&freelists->contexts, is_finalization, free_object);
|
||||||
clear_freelist(&freelists->async_gens, is_finalization, free_object);
|
clear_freelist(&freelists->async_gens, is_finalization, free_object);
|
||||||
clear_freelist(&freelists->async_gen_asends, is_finalization, free_object);
|
clear_freelist(&freelists->async_gen_asends, is_finalization, free_object);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "pycore_abstract.h" // _PyIndex_Check()
|
#include "pycore_abstract.h" // _PyIndex_Check()
|
||||||
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
|
#include "pycore_ceval.h" // _PyEval_GetBuiltin()
|
||||||
|
#include "pycore_freelist.h"
|
||||||
#include "pycore_long.h" // _PyLong_GetZero()
|
#include "pycore_long.h" // _PyLong_GetZero()
|
||||||
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
|
#include "pycore_modsupport.h" // _PyArg_NoKwnames()
|
||||||
#include "pycore_range.h"
|
#include "pycore_range.h"
|
||||||
|
@ -51,16 +52,18 @@ static rangeobject *
|
||||||
make_range_object(PyTypeObject *type, PyObject *start,
|
make_range_object(PyTypeObject *type, PyObject *start,
|
||||||
PyObject *stop, PyObject *step)
|
PyObject *stop, PyObject *step)
|
||||||
{
|
{
|
||||||
rangeobject *obj = NULL;
|
|
||||||
PyObject *length;
|
PyObject *length;
|
||||||
length = compute_range_length(start, stop, step);
|
length = compute_range_length(start, stop, step);
|
||||||
if (length == NULL) {
|
if (length == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
obj = PyObject_New(rangeobject, type);
|
rangeobject *obj = _Py_FREELIST_POP(rangeobject, ranges);
|
||||||
if (obj == NULL) {
|
if (obj == NULL) {
|
||||||
Py_DECREF(length);
|
obj = PyObject_New(rangeobject, type);
|
||||||
return NULL;
|
if (obj == NULL) {
|
||||||
|
Py_DECREF(length);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
obj->start = start;
|
obj->start = start;
|
||||||
obj->stop = stop;
|
obj->stop = stop;
|
||||||
|
@ -171,7 +174,7 @@ range_dealloc(PyObject *op)
|
||||||
Py_DECREF(r->stop);
|
Py_DECREF(r->stop);
|
||||||
Py_DECREF(r->step);
|
Py_DECREF(r->step);
|
||||||
Py_DECREF(r->length);
|
Py_DECREF(r->length);
|
||||||
PyObject_Free(r);
|
_Py_FREELIST_FREE(ranges, r, PyObject_Free);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long
|
||||||
|
@ -895,6 +898,12 @@ rangeiter_setstate(PyObject *op, PyObject *state)
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
rangeiter_dealloc(PyObject *self)
|
||||||
|
{
|
||||||
|
_Py_FREELIST_FREE(range_iters, (_PyRangeIterObject *)self, PyObject_Free);
|
||||||
|
}
|
||||||
|
|
||||||
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
|
PyDoc_STRVAR(reduce_doc, "Return state information for pickling.");
|
||||||
PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
|
PyDoc_STRVAR(setstate_doc, "Set state information for unpickling.");
|
||||||
|
|
||||||
|
@ -911,7 +920,7 @@ PyTypeObject PyRangeIter_Type = {
|
||||||
sizeof(_PyRangeIterObject), /* tp_basicsize */
|
sizeof(_PyRangeIterObject), /* tp_basicsize */
|
||||||
0, /* tp_itemsize */
|
0, /* tp_itemsize */
|
||||||
/* methods */
|
/* methods */
|
||||||
0, /* tp_dealloc */
|
rangeiter_dealloc, /* tp_dealloc */
|
||||||
0, /* tp_vectorcall_offset */
|
0, /* tp_vectorcall_offset */
|
||||||
0, /* tp_getattr */
|
0, /* tp_getattr */
|
||||||
0, /* tp_setattr */
|
0, /* tp_setattr */
|
||||||
|
@ -972,9 +981,14 @@ get_len_of_range(long lo, long hi, long step)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
fast_range_iter(long start, long stop, long step, long len)
|
fast_range_iter(long start, long stop, long step, long len)
|
||||||
{
|
{
|
||||||
_PyRangeIterObject *it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type);
|
_PyRangeIterObject *it = _Py_FREELIST_POP(_PyRangeIterObject, range_iters);
|
||||||
if (it == NULL)
|
if (it == NULL) {
|
||||||
return NULL;
|
it = PyObject_New(_PyRangeIterObject, &PyRangeIter_Type);
|
||||||
|
if (it == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(Py_IS_TYPE(it, &PyRangeIter_Type));
|
||||||
it->start = start;
|
it->start = start;
|
||||||
it->step = step;
|
it->step = step;
|
||||||
it->len = len;
|
it->len = len;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue