Skip to content

Commit

Permalink
pythongh-111968: Split _Py_dictkeys_freelist out of _Py_dict_freelist
Browse files Browse the repository at this point in the history
  • Loading branch information
corona10 committed Feb 15, 2024
1 parent 18343c0 commit 1710e24
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 14 deletions.
9 changes: 9 additions & 0 deletions Include/internal/pycore_freelist.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
41 changes: 27 additions & 14 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,25 +276,35 @@ 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


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
}
Expand All @@ -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
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 1710e24

Please sign in to comment.