From 1710e24c37065f814cae8ac11da9a02e1d703b08 Mon Sep 17 00:00:00 2001 From: Donghee Na Date: Thu, 15 Feb 2024 11:15:19 +0900 Subject: [PATCH] gh-111968: Split _Py_dictkeys_freelist out of _Py_dict_freelist --- Include/internal/pycore_freelist.h | 9 +++++++ Objects/dictobject.c | 41 ++++++++++++++++++++---------- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/Include/internal/pycore_freelist.h b/Include/internal/pycore_freelist.h index b365ca337eabc8..00945494789db1 100644 --- a/Include/internal/pycore_freelist.h +++ b/Include/internal/pycore_freelist.h @@ -71,6 +71,14 @@ struct _Py_dict_freelist { #ifdef WITH_FREELISTS /* Dictionary reuse scheme to save calls to malloc and free */ PyDictObject *free_list[PyDict_MAXFREELIST]; + int numfree; + int keys_numfree; +#endif +}; + +struct _Py_dictkeys_freelist { +#ifdef WITH_FREELISTS + /* Dictionary keys reuse scheme to save calls to malloc and free */ PyDictKeysObject *keys_free_list[PyDict_MAXFREELIST]; int numfree; int keys_numfree; @@ -119,6 +127,7 @@ struct _Py_object_freelists { struct _Py_tuple_freelist tuples; struct _Py_list_freelist lists; struct _Py_dict_freelist dicts; + struct _Py_dictkeys_freelist dictkeys; struct _Py_slice_freelist slices; struct _Py_context_freelist contexts; struct _Py_async_gen_freelist async_gens; diff --git a/Objects/dictobject.c b/Objects/dictobject.c index 11667b07ecfb4b..3ebdde597086c8 100644 --- a/Objects/dictobject.c +++ b/Objects/dictobject.c @@ -276,6 +276,13 @@ get_dict_freelist(void) struct _Py_object_freelists *freelists = _Py_object_freelists_GET(); return &freelists->dicts; } + +static struct _Py_dictkeys_freelist * +get_dictkeys_freelist(void) +{ + struct _Py_object_freelists *freelists = _Py_object_freelists_GET(); + return &freelists->dictkeys; +} #endif @@ -283,18 +290,21 @@ void _PyDict_ClearFreeList(struct _Py_object_freelists *freelists, int is_finalization) { #ifdef WITH_FREELISTS - struct _Py_dict_freelist *state = &freelists->dicts; - while (state->numfree > 0) { - PyDictObject *op = state->free_list[--state->numfree]; + struct _Py_dict_freelist *dict_freelist = &freelists->dicts; + while (dict_freelist->numfree > 0) { + PyDictObject *op = dict_freelist->free_list[--dict_freelist->numfree]; assert(PyDict_CheckExact(op)); PyObject_GC_Del(op); } - while (state->keys_numfree > 0) { - PyMem_Free(state->keys_free_list[--state->keys_numfree]); + struct _Py_dictkeys_freelist *dictkeys_freelist = &freelists->dictkeys; + while (dictkeys_freelist->keys_numfree > 0) { + PyMem_Free(dictkeys_freelist->keys_free_list[--dictkeys_freelist->keys_numfree]); } if (is_finalization) { - state->numfree = -1; - state->keys_numfree = -1; + dict_freelist->numfree = -1; + dict_freelist->keys_numfree = -1; + dictkeys_freelist->numfree = -1; + dictkeys_freelist->keys_numfree = -1; } #endif } @@ -314,6 +324,9 @@ _PyDict_DebugMallocStats(FILE *out) struct _Py_dict_freelist *dict_freelist = get_dict_freelist(); _PyDebugAllocatorStats(out, "free PyDictObject", dict_freelist->numfree, sizeof(PyDictObject)); + struct _Py_dictkeys_freelist *dictkeys_freelist = get_dictkeys_freelist(); + _PyDebugAllocatorStats(out, "free PyDictKeysObject", + dictkeys_freelist->numfree, sizeof(PyDictKeysObject)); #endif } @@ -663,9 +676,9 @@ new_keys_object(PyInterpreterState *interp, uint8_t log2_size, bool unicode) } #ifdef WITH_FREELISTS - struct _Py_dict_freelist *dict_freelist = get_dict_freelist(); - if (log2_size == PyDict_LOG_MINSIZE && unicode && dict_freelist->keys_numfree > 0) { - dk = dict_freelist->keys_free_list[--dict_freelist->keys_numfree]; + struct _Py_dictkeys_freelist *dictkey_freelist = get_dictkeys_freelist(); + if (log2_size == PyDict_LOG_MINSIZE && unicode && dictkey_freelist->keys_numfree > 0) { + dk = dictkey_freelist->keys_free_list[--dictkey_freelist->keys_numfree]; OBJECT_STAT_INC(from_freelist); } else @@ -698,12 +711,12 @@ static void free_keys_object(PyDictKeysObject *keys) { #ifdef WITH_FREELISTS - struct _Py_dict_freelist *dict_freelist = get_dict_freelist(); + struct _Py_dictkeys_freelist *dictkey_freelist = get_dictkeys_freelist(); if (DK_LOG_SIZE(keys) == PyDict_LOG_MINSIZE - && dict_freelist->keys_numfree < PyDict_MAXFREELIST - && dict_freelist->keys_numfree >= 0 + && dictkey_freelist->keys_numfree < PyDict_MAXFREELIST + && dictkey_freelist->keys_numfree >= 0 && DK_IS_UNICODE(keys)) { - dict_freelist->keys_free_list[dict_freelist->keys_numfree++] = keys; + dictkey_freelist->keys_free_list[dictkey_freelist->keys_numfree++] = keys; OBJECT_STAT_INC(to_freelist); return; }