Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork32.3k
gh-133136: Limit excess memory held by QSBR#135107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes from1 commit
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
The free threading build uses QSBR to delay the freeing of dictionarykeys and list arrays when the objects are accessed by multiple threadsin order to allow concurrent reads to proceeed with holding the objectlock. The requests are processed in batches to reduce executionoverhead, but for large memory blocks this can lead to excess memoryusage.Take into account the size of the memory block when deciding when toprocess QSBR requests.
- Loading branch information
Uh oh!
There was an error while loading.Please reload this page.
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
Limit excess memory usage in the :term:`free threading` build when a | ||
large dictionary or list is resized and accessed by multiple threads. |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1141,8 +1141,27 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
static int | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
should_advance_qsbr(_PyThreadStateImpl *tstate, size_t size) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Check warning on line 1145 in Objects/obmalloc.c
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// If the deferred memory exceeds 1 MiB, we force an advance in the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// shared QSBR sequence number to limit excess memory usage. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
static const size_t QSBR_DEFERRED_LIMIT = 1024 * 1024; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (size > QSBR_DEFERRED_LIMIT) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tstate->qsbr->memory_deferred = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tstate->qsbr->memory_deferred += size; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (tstate->qsbr->memory_deferred > QSBR_DEFERRED_LIMIT) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tstate->qsbr->memory_deferred = 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return 1; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return 0; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines +1146 to +1162 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Do we need early return here? Suggested change
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
static void | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
free_delayed(uintptr_t ptr, size_t size) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#ifndef Py_GIL_DISABLED | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
free_work_item(ptr, NULL, NULL); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@@ -1200,23 +1219,29 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assert(buf != NULL && buf->wr_idx < WORK_ITEMS_PER_CHUNK); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
uint64_t seq; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
int force_advance = should_advance_qsbr(tstate, size); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (force_advance) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
seq = _Py_qsbr_advance(tstate->qsbr->shared); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
seq = _Py_qsbr_deferred_advance(tstate->qsbr); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf->array[buf->wr_idx].ptr = ptr; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf->array[buf->wr_idx].qsbr_goal = seq; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
buf->wr_idx++; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (buf->wr_idx == WORK_ITEMS_PER_CHUNK || force_advance) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_PyMem_ProcessDelayed((PyThreadState *)tstate); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
void | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
_PyMem_FreeDelayed(void *ptr, size_t size) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assert(!((uintptr_t)ptr & 0x01)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (ptr != NULL) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
free_delayed((uintptr_t)ptr, size); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@@ -1226,7 +1251,7 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
assert(!((uintptr_t)ptr & 0x01)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
if (ptr != NULL) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
free_delayed(((uintptr_t)ptr)|0x01, 64); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
#endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading.Please reload this page.