From: T. Wouters Date: Tue, 24 Mar 2026 01:27:57 +0000 (+0100) Subject: [3.13] gh-142183: Cache one datachunk per tstate to prevent alloc/dealloc thrashing... X-Git-Tag: v3.13.13~60 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=684e7af8cd61bca4914d0ec01b814ff530d5a123;p=thirdparty%2FPython%2Fcpython.git [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> --- diff --git a/Doc/data/python3.13.abi b/Doc/data/python3.13.abi index d02189517317..e0588167eba0 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 f005729fff11..72a4969a2ad6 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 000000000000..827224dc71e8 --- /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 68e76e4aed5a..07c69b92d527 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);