mirror of
https://github.com/python/cpython.git
synced 2026-04-14 07:41:00 +00:00
[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 commit706fd4ec08) (cherry picked from commit19cbcc0f85) 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>
This commit is contained in:
parent
0d82ce82f1
commit
684e7af8cd
4 changed files with 663 additions and 635 deletions
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue