bpo-40521: Make tuple free list per-interpreter (GH-20247) · python/cpython@69ac6e5

@@ -14,28 +14,6 @@ class tuple "PyTupleObject *" "&PyTuple_Type"

14141515

#include "clinic/tupleobject.c.h"

161617-

/* Speed optimization to avoid frequent malloc/free of small tuples */

18-

#ifndef PyTuple_MAXSAVESIZE

19-

#define PyTuple_MAXSAVESIZE 20 /* Largest tuple to save on free list */

20-

#endif

21-

#ifndef PyTuple_MAXFREELIST

22-

#define PyTuple_MAXFREELIST 2000 /* Maximum number of tuples of each size to save */

23-

#endif

24-25-

/* bpo-40521: tuple free lists are shared by all interpreters. */

26-

#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS

27-

# undef PyTuple_MAXSAVESIZE

28-

# define PyTuple_MAXSAVESIZE 0

29-

#endif

30-31-

#if PyTuple_MAXSAVESIZE > 0

32-

/* Entries 1 up to PyTuple_MAXSAVESIZE are free lists, entry 0 is the empty

33-

tuple () of which at most one instance will be allocated.

34-

*/

35-

static PyTupleObject *free_list[PyTuple_MAXSAVESIZE];

36-

static int numfree[PyTuple_MAXSAVESIZE];

37-

#endif

38-3917

static inline void

4018

tuple_gc_track(PyTupleObject *op)

4119

{

@@ -47,14 +25,14 @@ void

4725

_PyTuple_DebugMallocStats(FILE *out)

4826

{

4927

#if PyTuple_MAXSAVESIZE > 0

50-

int i;

51-

char buf[128];

52-

for (i = 1; i < PyTuple_MAXSAVESIZE; i++) {

28+

PyInterpreterState *interp = _PyInterpreterState_GET();

29+

struct _Py_tuple_state *state = &interp->tuple;

30+

for (int i = 1; i < PyTuple_MAXSAVESIZE; i++) {

31+

char buf[128];

5332

PyOS_snprintf(buf, sizeof(buf),

5433

"free %d-sized PyTupleObject", i);

55-

_PyDebugAllocatorStats(out,

56-

buf,

57-

numfree[i], _PyObject_VAR_SIZE(&PyTuple_Type, i));

34+

_PyDebugAllocatorStats(out, buf, state->numfree[i],

35+

_PyObject_VAR_SIZE(&PyTuple_Type, i));

5836

}

5937

#endif

6038

}

@@ -68,18 +46,18 @@ _PyTuple_DebugMallocStats(FILE *out)

6846

which wraps this function).

6947

*/

7048

static PyTupleObject *

71-

tuple_alloc(Py_ssize_t size)

49+

tuple_alloc(struct _Py_tuple_state *state, Py_ssize_t size)

7250

{

7351

PyTupleObject *op;

7452

if (size < 0) {

7553

PyErr_BadInternalCall();

7654

return NULL;

7755

}

7856

#if PyTuple_MAXSAVESIZE > 0

79-

if (size < PyTuple_MAXSAVESIZE && (op = free_list[size]) != NULL) {

57+

if (size < PyTuple_MAXSAVESIZE && (op = state->free_list[size]) != NULL) {

8058

assert(size != 0);

81-

free_list[size] = (PyTupleObject *) op->ob_item[0];

82-

numfree[size]--;

59+

state->free_list[size] = (PyTupleObject *) op->ob_item[0];

60+

state->numfree[size]--;

8361

/* Inline PyObject_InitVar */

8462

#ifdef Py_TRACE_REFS

8563

Py_SET_SIZE(op, size);

@@ -107,13 +85,15 @@ PyTuple_New(Py_ssize_t size)

10785

{

10886

PyTupleObject *op;

10987

#if PyTuple_MAXSAVESIZE > 0

110-

if (size == 0 && free_list[0]) {

111-

op = free_list[0];

88+

PyInterpreterState *interp = _PyInterpreterState_GET();

89+

struct _Py_tuple_state *state = &interp->tuple;

90+

if (size == 0 && state->free_list[0]) {

91+

op = state->free_list[0];

11292

Py_INCREF(op);

11393

return (PyObject *) op;

11494

}

11595

#endif

116-

op = tuple_alloc(size);

96+

op = tuple_alloc(state, size);

11797

if (op == NULL) {

11898

return NULL;

11999

}

@@ -122,8 +102,8 @@ PyTuple_New(Py_ssize_t size)

122102

}

123103

#if PyTuple_MAXSAVESIZE > 0

124104

if (size == 0) {

125-

free_list[0] = op;

126-

++numfree[0];

105+

state->free_list[0] = op;

106+

++state->numfree[0];

127107

Py_INCREF(op); /* extra INCREF so that this is never freed */

128108

}

129109

#endif

@@ -210,8 +190,11 @@ PyTuple_Pack(Py_ssize_t n, ...)

210190

return PyTuple_New(0);

211191

}

212192193+

PyInterpreterState *interp = _PyInterpreterState_GET();

194+

struct _Py_tuple_state *state = &interp->tuple;

195+213196

va_start(vargs, n);

214-

PyTupleObject *result = tuple_alloc(n);

197+

PyTupleObject *result = tuple_alloc(state, n);

215198

if (result == NULL) {

216199

va_end(vargs);

217200

return NULL;

@@ -233,22 +216,24 @@ PyTuple_Pack(Py_ssize_t n, ...)

233216

static void

234217

tupledealloc(PyTupleObject *op)

235218

{

236-

Py_ssize_t i;

237219

Py_ssize_t len = Py_SIZE(op);

238220

PyObject_GC_UnTrack(op);

239221

Py_TRASHCAN_BEGIN(op, tupledealloc)

240222

if (len > 0) {

241-

i = len;

242-

while (--i >= 0)

223+

Py_ssize_t i = len;

224+

while (--i >= 0) {

243225

Py_XDECREF(op->ob_item[i]);

226+

}

244227

#if PyTuple_MAXSAVESIZE > 0

228+

PyInterpreterState *interp = _PyInterpreterState_GET();

229+

struct _Py_tuple_state *state = &interp->tuple;

245230

if (len < PyTuple_MAXSAVESIZE &&

246-

numfree[len] < PyTuple_MAXFREELIST &&

231+

state->numfree[len] < PyTuple_MAXFREELIST &&

247232

Py_IS_TYPE(op, &PyTuple_Type))

248233

{

249-

op->ob_item[0] = (PyObject *) free_list[len];

250-

numfree[len]++;

251-

free_list[len] = op;

234+

op->ob_item[0] = (PyObject *) state->free_list[len];

235+

state->numfree[len]++;

236+

state->free_list[len] = op;

252237

goto done; /* return */

253238

}

254239

#endif

@@ -423,7 +408,9 @@ _PyTuple_FromArray(PyObject *const *src, Py_ssize_t n)

423408

return PyTuple_New(0);

424409

}

425410426-

PyTupleObject *tuple = tuple_alloc(n);

411+

PyInterpreterState *interp = _PyInterpreterState_GET();

412+

struct _Py_tuple_state *state = &interp->tuple;

413+

PyTupleObject *tuple = tuple_alloc(state, n);

427414

if (tuple == NULL) {

428415

return NULL;

429416

}

@@ -481,7 +468,8 @@ tupleconcat(PyTupleObject *a, PyObject *bb)

481468

Py_TYPE(bb)->tp_name);

482469

return NULL;

483470

}

484-

#define b ((PyTupleObject *)bb)

471+

PyTupleObject *b = (PyTupleObject *)bb;

472+485473

if (Py_SIZE(b) == 0 && PyTuple_CheckExact(a)) {

486474

Py_INCREF(a);

487475

return (PyObject *)a;

@@ -492,7 +480,9 @@ tupleconcat(PyTupleObject *a, PyObject *bb)

492480

return PyTuple_New(0);

493481

}

494482495-

np = tuple_alloc(size);

483+

PyInterpreterState *interp = _PyInterpreterState_GET();

484+

struct _Py_tuple_state *state = &interp->tuple;

485+

np = tuple_alloc(state, size);

496486

if (np == NULL) {

497487

return NULL;

498488

}

@@ -512,7 +502,6 @@ tupleconcat(PyTupleObject *a, PyObject *bb)

512502

}

513503

tuple_gc_track(np);

514504

return (PyObject *)np;

515-

#undef b

516505

}

517506518507

static PyObject *

@@ -536,7 +525,9 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)

536525

if (n > PY_SSIZE_T_MAX / Py_SIZE(a))

537526

return PyErr_NoMemory();

538527

size = Py_SIZE(a) * n;

539-

np = tuple_alloc(size);

528+

PyInterpreterState *interp = _PyInterpreterState_GET();

529+

struct _Py_tuple_state *state = &interp->tuple;

530+

np = tuple_alloc(state, size);

540531

if (np == NULL)

541532

return NULL;

542533

p = np->ob_item;

@@ -801,7 +792,9 @@ tuplesubscript(PyTupleObject* self, PyObject* item)

801792

return (PyObject *)self;

802793

}

803794

else {

804-

PyTupleObject* result = tuple_alloc(slicelength);

795+

PyInterpreterState *interp = _PyInterpreterState_GET();

796+

struct _Py_tuple_state *state = &interp->tuple;

797+

PyTupleObject* result = tuple_alloc(state, slicelength);

805798

if (!result) return NULL;

806799807800

src = self->ob_item;

@@ -963,13 +956,14 @@ _PyTuple_Resize(PyObject **pv, Py_ssize_t newsize)

963956

}

964957965958

void

966-

_PyTuple_ClearFreeList(void)

959+

_PyTuple_ClearFreeList(PyThreadState *tstate)

967960

{

968961

#if PyTuple_MAXSAVESIZE > 0

962+

struct _Py_tuple_state *state = &tstate->interp->tuple;

969963

for (Py_ssize_t i = 1; i < PyTuple_MAXSAVESIZE; i++) {

970-

PyTupleObject *p = free_list[i];

971-

free_list[i] = NULL;

972-

numfree[i] = 0;

964+

PyTupleObject *p = state->free_list[i];

965+

state->free_list[i] = NULL;

966+

state->numfree[i] = 0;

973967

while (p) {

974968

PyTupleObject *q = p;

975969

p = (PyTupleObject *)(p->ob_item[0]);

@@ -981,14 +975,15 @@ _PyTuple_ClearFreeList(void)

981975

}

982976983977

void

984-

_PyTuple_Fini(void)

978+

_PyTuple_Fini(PyThreadState *tstate)

985979

{

986980

#if PyTuple_MAXSAVESIZE > 0

981+

struct _Py_tuple_state *state = &tstate->interp->tuple;

987982

/* empty tuples are used all over the place and applications may

988983

* rely on the fact that an empty tuple is a singleton. */

989-

Py_CLEAR(free_list[0]);

984+

Py_CLEAR(state->free_list[0]);

990985991-

_PyTuple_ClearFreeList();

986+

_PyTuple_ClearFreeList(tstate);

992987

#endif

993988

}

994989