_tracemalloc: use compact key for traces
Issue #26588: Optimize memory footprint of _tracemalloc before non-zero domain is used. Start with compact key (Py_uintptr_t) and also switch to pointer_t key when the first memory block with a non-zero domain is tracked.
This commit is contained in:
parent
cc73932125
commit
5e14a38e8e
|
@ -43,7 +43,7 @@ static struct {
|
||||||
/* use domain in trace key?
|
/* use domain in trace key?
|
||||||
Variable protected by the GIL. */
|
Variable protected by the GIL. */
|
||||||
int use_domain;
|
int use_domain;
|
||||||
} tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 1, 1};
|
} tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 1, 0};
|
||||||
|
|
||||||
#if defined(TRACE_RAW_MALLOC) && defined(WITH_THREAD)
|
#if defined(TRACE_RAW_MALLOC) && defined(WITH_THREAD)
|
||||||
/* This lock is needed because tracemalloc_free() is called without
|
/* This lock is needed because tracemalloc_free() is called without
|
||||||
|
@ -519,6 +519,58 @@ traceback_new(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
tracemalloc_use_domain_cb(_Py_hashtable_t *old_traces,
|
||||||
|
_Py_hashtable_entry_t *entry, void *user_data)
|
||||||
|
{
|
||||||
|
Py_uintptr_t ptr;
|
||||||
|
pointer_t key;
|
||||||
|
_Py_hashtable_t *new_traces = (_Py_hashtable_t *)user_data;
|
||||||
|
const void *pdata = _Py_HASHTABLE_ENTRY_PDATA(old_traces, entry);
|
||||||
|
|
||||||
|
_Py_HASHTABLE_ENTRY_READ_KEY(old_traces, entry, ptr);
|
||||||
|
key.ptr = ptr;
|
||||||
|
key.domain = DEFAULT_DOMAIN;
|
||||||
|
|
||||||
|
return _Py_hashtable_set(new_traces,
|
||||||
|
sizeof(key), &key,
|
||||||
|
old_traces->data_size, pdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Convert tracemalloc_traces from compact key (Py_uintptr_t) to pointer_t key.
|
||||||
|
* Return 0 on success, -1 on error. */
|
||||||
|
static int
|
||||||
|
tracemalloc_use_domain(void)
|
||||||
|
{
|
||||||
|
_Py_hashtable_t *new_traces = NULL;
|
||||||
|
|
||||||
|
assert(!tracemalloc_config.use_domain);
|
||||||
|
|
||||||
|
new_traces = hashtable_new(sizeof(pointer_t),
|
||||||
|
sizeof(trace_t),
|
||||||
|
hashtable_hash_pointer_t,
|
||||||
|
hashtable_compare_pointer_t);
|
||||||
|
if (new_traces == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_Py_hashtable_foreach(tracemalloc_traces, tracemalloc_use_domain_cb,
|
||||||
|
new_traces) < 0)
|
||||||
|
{
|
||||||
|
_Py_hashtable_destroy(new_traces);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
_Py_hashtable_destroy(tracemalloc_traces);
|
||||||
|
tracemalloc_traces = new_traces;
|
||||||
|
|
||||||
|
tracemalloc_config.use_domain = 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
tracemalloc_remove_trace(_PyTraceMalloc_domain_t domain, Py_uintptr_t ptr)
|
tracemalloc_remove_trace(_PyTraceMalloc_domain_t domain, Py_uintptr_t ptr)
|
||||||
{
|
{
|
||||||
|
@ -563,6 +615,14 @@ tracemalloc_add_trace(_PyTraceMalloc_domain_t domain, Py_uintptr_t ptr,
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!tracemalloc_config.use_domain && domain != DEFAULT_DOMAIN) {
|
||||||
|
/* first trace using a non-zero domain whereas traces use compact
|
||||||
|
(Py_uintptr_t) keys: switch to pointer_t keys. */
|
||||||
|
if (tracemalloc_use_domain() < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (tracemalloc_config.use_domain) {
|
if (tracemalloc_config.use_domain) {
|
||||||
entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
|
entry = _Py_HASHTABLE_GET_ENTRY(tracemalloc_traces, key);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue