mirror of
https://github.com/python/cpython.git
synced 2026-04-14 15:50:50 +00:00
[3.14] 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 706fd4ec08)
Co-authored-by: T. Wouters <thomas@python.org>
Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
This commit is contained in:
parent
6980b94c3a
commit
19cbcc0f85
4 changed files with 4347 additions and 4310 deletions
|
|
@ -1575,6 +1575,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->current_executor = NULL;
|
||||
tstate->dict_global_version = 0;
|
||||
|
|
@ -1714,6 +1715,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
|
||||
|
|
@ -3029,9 +3035,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 -
|
||||
|
|
@ -3067,12 +3084,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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue