From 684e7af8cd61bca4914d0ec01b814ff530d5a123 Mon Sep 17 00:00:00 2001 From: "T. Wouters" Date: Tue, 24 Mar 2026 02:27:57 +0100 Subject: [PATCH] [3.13] gh-142183: Cache one datachunk per tstate to prevent alloc/dealloc thrashing (GH-145789) (#146123) * gh-142183: Cache one datachunk per tstate to prevent alloc/dealloc thrashing (GH-145789) (#145828) Cache one datachunk per tstate to prevent alloc/dealloc thrashing when repeatedly hitting the same call depth at exactly the wrong boundary. Move new _ts member to the end to not mess up remote debuggers' ideas of the struct's layout. (The struct is only created by the runtime, and the new field only used by the runtime, so it should be safe.) (cherry picked from commit 706fd4ec08acbf1b1def3630017ebe55d224adfa) (cherry picked from commit 19cbcc0f85f30954293dbd92d718d5b81880b092) Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com> Co-authored-by: Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> --- Doc/data/python3.13.abi | 1265 +++++++++-------- Include/cpython/pystate.h | 2 + ...-03-11-00-13-59.gh-issue-142183.2iVhJH.rst | 1 + Python/pystate.c | 30 +- 4 files changed, 663 insertions(+), 635 deletions(-) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst diff --git a/Doc/data/python3.13.abi b/Doc/data/python3.13.abi index d0218951731..e0588167eba 100644 --- a/Doc/data/python3.13.abi +++ b/Doc/data/python3.13.abi @@ -1670,7 +1670,7 @@ - + @@ -1688,7 +1688,7 @@ - + @@ -1703,7 +1703,7 @@ - + @@ -1737,10 +1737,10 @@ - + - + @@ -1828,11 +1828,11 @@ - + - + @@ -1844,14 +1844,14 @@ - + - + @@ -1870,7 +1870,7 @@ - + @@ -1898,7 +1898,7 @@ - + @@ -1940,7 +1940,7 @@ - + @@ -1957,7 +1957,7 @@ - + @@ -1974,7 +1974,7 @@ - + @@ -2001,13 +2001,13 @@ - + - + @@ -2015,7 +2015,7 @@ - + @@ -2100,7 +2100,7 @@ - + @@ -2125,7 +2125,7 @@ - + @@ -2164,7 +2164,7 @@ - + @@ -3393,7 +3393,7 @@ - + @@ -3447,7 +3447,7 @@ - + @@ -3558,7 +3558,7 @@ - + @@ -3567,7 +3567,7 @@ - + @@ -3653,7 +3653,7 @@ - + @@ -3675,12 +3675,12 @@ - + - + @@ -3697,7 +3697,7 @@ - + @@ -3896,7 +3896,7 @@ - + @@ -3973,7 +3973,7 @@ - + @@ -4010,7 +4010,7 @@ - + @@ -4070,7 +4070,7 @@ - + @@ -4817,7 +4817,7 @@ - + @@ -4855,7 +4855,7 @@ - + @@ -5175,35 +5175,35 @@ - - + + - - - + + + - - + + - - + + - - - + + + - - - + + + - + @@ -5261,7 +5261,7 @@ - + @@ -5461,7 +5461,7 @@ - + @@ -5480,7 +5480,7 @@ - + @@ -5665,7 +5665,7 @@ - + @@ -5740,7 +5740,7 @@ - + @@ -5762,10 +5762,10 @@ - + - + @@ -5818,7 +5818,7 @@ - + @@ -6023,7 +6023,7 @@ - + @@ -6140,18 +6140,18 @@ - + - + - + - + @@ -6282,8 +6282,8 @@ - - + + @@ -6331,170 +6331,170 @@ - - + + - - - - + + + + - - - - - + + + + + - - - + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - - - + + + + - - - - - + + + + + - - + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - + + + + - - - - - + + + + + - - - - + + + + - - + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - + + + + - - - + + + - - + + - - - + + + - - - + + + - - + + - - + + @@ -6503,11 +6503,11 @@ - + - + @@ -6848,7 +6848,7 @@ - + @@ -6937,7 +6937,7 @@ - + @@ -7006,11 +7006,6 @@ - - - - - @@ -7107,41 +7102,41 @@ - - - - + + + + - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - + + + - + @@ -7317,7 +7312,7 @@ - + @@ -7410,16 +7405,16 @@ - - + + - - + + - + @@ -7432,6 +7427,11 @@ + + + + + @@ -7453,7 +7453,7 @@ - + @@ -7542,7 +7542,7 @@ - + @@ -7648,7 +7648,7 @@ - + @@ -7661,7 +7661,7 @@ - + @@ -7698,11 +7698,6 @@ - - - - - @@ -7745,7 +7740,7 @@ - + @@ -7919,6 +7914,11 @@ + + + + + @@ -7941,7 +7941,7 @@ - + @@ -7969,7 +7969,7 @@ - + @@ -7996,7 +7996,7 @@ - + @@ -8055,7 +8055,7 @@ - + @@ -8189,7 +8189,7 @@ - + @@ -8201,12 +8201,12 @@ - - + + - + @@ -8619,7 +8619,7 @@ - + @@ -9207,13 +9207,13 @@ - + - + - + @@ -9407,7 +9407,7 @@ - + @@ -9485,7 +9485,7 @@ - + @@ -9500,7 +9500,7 @@ - + @@ -9519,7 +9519,7 @@ - + @@ -9579,30 +9579,30 @@ - - - + + + - - + + - - + + - - - + + + - - + + - + @@ -9630,7 +9630,7 @@ - + @@ -9675,27 +9675,27 @@ - - - + + + - - - + + + - - - + + + - - + + - + @@ -9715,7 +9715,7 @@ - + @@ -9880,114 +9880,114 @@ - - + + - - + + - - + + - - + + - - + + - - - - - + + + + + - - - - + + + + - - + + - - + + - - + + - - - + + + - - + + - - + + - - - + + + - - - - + + + + - - - - - + + + + + - - - + + + - - + + - - + + - - - + + + - - - + + + - - - - - + + + + + - + @@ -10005,7 +10005,7 @@ - + @@ -10027,7 +10027,7 @@ - + @@ -10689,7 +10689,7 @@ - + @@ -10703,7 +10703,7 @@ - + @@ -10759,7 +10759,7 @@ - + @@ -11892,7 +11892,7 @@ - + @@ -11977,7 +11977,7 @@ - + @@ -12049,7 +12049,7 @@ - + @@ -13346,7 +13346,7 @@ - + @@ -13385,7 +13385,7 @@ - + @@ -13444,10 +13444,10 @@ - + - + @@ -14713,29 +14713,29 @@ - + - + - + - + - + - - + + - - + + @@ -14819,7 +14819,7 @@ - + @@ -14943,6 +14943,9 @@ + + + @@ -14973,7 +14976,7 @@ - + @@ -17251,10 +17254,10 @@ - + - + @@ -19705,7 +19708,7 @@ - + @@ -19713,7 +19716,7 @@ - + @@ -19932,7 +19935,7 @@ - + @@ -20143,10 +20146,10 @@ - + - + @@ -20998,7 +21001,7 @@ - + @@ -21275,17 +21278,17 @@ - + - + - + - + @@ -22618,7 +22621,7 @@ - + @@ -23145,7 +23148,7 @@ - + @@ -23207,7 +23210,7 @@ - + @@ -23258,7 +23261,7 @@ - + @@ -23283,7 +23286,7 @@ - + @@ -23460,14 +23463,14 @@ - + - + @@ -23476,7 +23479,7 @@ - + @@ -23496,7 +23499,7 @@ - + @@ -23530,7 +23533,7 @@ - + @@ -23598,7 +23601,7 @@ - + @@ -23753,13 +23756,13 @@ - + - + @@ -23900,7 +23903,7 @@ - + @@ -23944,7 +23947,7 @@ - + @@ -24425,7 +24428,7 @@ - + @@ -24564,7 +24567,7 @@ - + @@ -24653,7 +24656,7 @@ - + @@ -25164,7 +25167,7 @@ - + @@ -25253,7 +25256,7 @@ - + @@ -25302,7 +25305,7 @@ - + @@ -25409,21 +25412,21 @@ - + - + - + - - + + - + - + @@ -25571,76 +25574,76 @@ - - - + + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - + + + + - - - - + + + + - - + + - - - - - + - - - - + + + + + + + + - - - - - + + + + + - - - - + + + + @@ -25657,7 +25660,7 @@ - + @@ -25737,37 +25740,37 @@ - - - + + + - - - - - - + + + + + + - - - - + + + + - - - + + + - + - + @@ -25892,7 +25895,7 @@ - + @@ -25902,7 +25905,7 @@ - + @@ -26021,7 +26024,7 @@ - + @@ -26042,7 +26045,7 @@ - + @@ -26075,7 +26078,7 @@ - + @@ -26132,7 +26135,7 @@ - + @@ -26186,14 +26189,14 @@ - + - + @@ -26267,21 +26270,21 @@ - + - + - + - + @@ -26290,7 +26293,7 @@ - + @@ -26334,7 +26337,7 @@ - + @@ -26517,116 +26520,116 @@ - - + + - - + + - - + + - - + + - - - - + + + + - - - + + + - - + + - - - + + + - - + + - - - + + + - + - + - - - + + + - - - - + + + + - - - - - + + + + + - - - - - + + + + + - - + + - - + + - - + + - - - - - - + + + + + + - - + + - - - + + + - + - + @@ -26910,31 +26913,31 @@ - - - - + + + + - - - - - + + + + + - - + + - + - + - + @@ -27064,7 +27067,7 @@ - + @@ -27085,7 +27088,7 @@ - + @@ -27192,7 +27195,7 @@ - + @@ -27219,7 +27222,7 @@ - + @@ -27369,7 +27372,7 @@ - + @@ -27439,44 +27442,44 @@ - - - - + + + + - - - - + + + + - - + + - - + + - - + + - - + + - - - + + + - + - + @@ -27510,7 +27513,7 @@ - + @@ -27519,7 +27522,7 @@ - + @@ -27570,7 +27573,7 @@ - + @@ -27628,7 +27631,7 @@ - + @@ -27637,7 +27640,7 @@ - + @@ -27651,7 +27654,7 @@ - + @@ -27724,7 +27727,7 @@ - + @@ -27736,7 +27739,7 @@ - + @@ -27821,7 +27824,7 @@ - + @@ -28450,45 +28453,45 @@ - + - + - - + + - - - + + + - - + + - - + + - - - + + + - - + + - - - + + + - + @@ -28679,69 +28682,69 @@ - - + + - - + + - + - - + + - - + + - - - + + + - + - + - - + + - - + + - + - - + + - - - + + + - - + + - + - + @@ -28755,7 +28758,7 @@ - + @@ -28952,7 +28955,7 @@ - + @@ -29145,7 +29148,7 @@ - + @@ -29176,7 +29179,7 @@ - + @@ -29184,10 +29187,10 @@ - + - + @@ -29388,7 +29391,7 @@ - + @@ -29412,7 +29415,7 @@ - + diff --git a/Include/cpython/pystate.h b/Include/cpython/pystate.h index f005729fff1..72a4969a2ad 100644 --- a/Include/cpython/pystate.h +++ b/Include/cpython/pystate.h @@ -200,6 +200,8 @@ struct _ts { The PyThreadObject must hold the only reference to this value. */ PyObject *threading_local_sentinel; + + _PyStackChunk *datastack_cached_chunk; }; #ifdef Py_DEBUG diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst new file mode 100644 index 00000000000..827224dc71e --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2026-03-11-00-13-59.gh-issue-142183.2iVhJH.rst @@ -0,0 +1 @@ +Avoid a pathological case where repeated calls at a specific stack depth could be significantly slower. diff --git a/Python/pystate.c b/Python/pystate.c index 68e76e4aed5..07c69b92d52 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -1521,6 +1521,7 @@ init_threadstate(_PyThreadStateImpl *_tstate, tstate->datastack_chunk = NULL; tstate->datastack_top = NULL; tstate->datastack_limit = NULL; + tstate->datastack_cached_chunk = NULL; tstate->what_event = -1; tstate->previous_executor = NULL; tstate->dict_global_version = 0; @@ -1655,6 +1656,11 @@ clear_datastack(PyThreadState *tstate) _PyObject_VirtualFree(chunk, chunk->size); chunk = prev; } + if (tstate->datastack_cached_chunk != NULL) { + _PyObject_VirtualFree(tstate->datastack_cached_chunk, + tstate->datastack_cached_chunk->size); + tstate->datastack_cached_chunk = NULL; + } } void @@ -2934,9 +2940,20 @@ push_chunk(PyThreadState *tstate, int size) while (allocate_size < (int)sizeof(PyObject*)*(size + MINIMUM_OVERHEAD)) { allocate_size *= 2; } - _PyStackChunk *new = allocate_chunk(allocate_size, tstate->datastack_chunk); - if (new == NULL) { - return NULL; + _PyStackChunk *new; + if (tstate->datastack_cached_chunk != NULL + && (size_t)allocate_size <= tstate->datastack_cached_chunk->size) + { + new = tstate->datastack_cached_chunk; + tstate->datastack_cached_chunk = NULL; + new->previous = tstate->datastack_chunk; + new->top = 0; + } + else { + new = allocate_chunk(allocate_size, tstate->datastack_chunk); + if (new == NULL) { + return NULL; + } } if (tstate->datastack_chunk) { tstate->datastack_chunk->top = tstate->datastack_top - @@ -2972,12 +2989,17 @@ _PyThreadState_PopFrame(PyThreadState *tstate, _PyInterpreterFrame * frame) if (base == &tstate->datastack_chunk->data[0]) { _PyStackChunk *chunk = tstate->datastack_chunk; _PyStackChunk *previous = chunk->previous; + _PyStackChunk *cached = tstate->datastack_cached_chunk; // push_chunk ensures that the root chunk is never popped: assert(previous); tstate->datastack_top = &previous->data[previous->top]; tstate->datastack_chunk = previous; - _PyObject_VirtualFree(chunk, chunk->size); tstate->datastack_limit = (PyObject **)(((char *)previous) + previous->size); + chunk->previous = NULL; + if (cached != NULL) { + _PyObject_VirtualFree(cached, cached->size); + } + tstate->datastack_cached_chunk = chunk; } else { assert(tstate->datastack_top);