Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 35.2k
GH-100240: Generic freelist, applied to ints#101453
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 our terms of service and privacy 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 from all commits
e953c57cf99ee48a6e6a3fe65f49a33061f6b312e01d811985609e30b8b1879460d12c2e2a86142ee27fa9e76ad113472778592b9044743e827b81b51c6c3ccfb886dFile 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
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -91,6 +91,80 @@ PyAPI_FUNC(int) _PyMem_GetAllocatorName( | ||
| PyAPI_FUNC(int) _PyMem_SetupAllocators(PyMemAllocatorName allocator); | ||
| /* Free lists. | ||
| * | ||
| * Free lists have a pointer to their first entry and | ||
| * the amount of space available allowing fast checks | ||
| * for emptiness and fullness. | ||
| * When empty they are half filled and when full they are | ||
| * completely emptied. This helps the underlying allocator | ||
| * avoid fragmentation and helps performance. | ||
| */ | ||
| typedef struct _freelist { | ||
| void *ptr; | ||
| uint32_t space; | ||
| uint16_t size; | ||
| uint16_t capacity; | ||
| #ifdef Py_STATS | ||
| int size_class; | ||
| #endif | ||
| } _PyFreeList; | ||
| extern void *_PyFreeList_HalfFillAndAllocate(_PyFreeList *list); | ||
| extern void _PyFreeList_FreeToFull(_PyFreeList *list, void *ptr); | ||
| extern void _PyFreeList_Clear(_PyFreeList *list); | ||
| extern void _PyFreeList_Disable(_PyFreeList *list); | ||
| static inline void * | ||
| _PyFreeList_Alloc(_PyFreeList *list) { | ||
| #ifdef Py_STATS | ||
| if (_py_stats) _py_stats->freelist_stats[list->size_class].allocations++; | ||
| #endif | ||
| if (list->ptr != NULL) { | ||
| void *result = list->ptr; | ||
| list->ptr = *((void **)result); | ||
| list->space++; | ||
| return result; | ||
| } | ||
| #ifdef Py_STATS | ||
| if (_py_stats) _py_stats->freelist_stats[list->size_class].empty++; | ||
| #endif | ||
| return _PyFreeList_HalfFillAndAllocate(list); | ||
| } | ||
| static inline void | ||
| _PyFreeList_Free(_PyFreeList *list, void *ptr) { | ||
| #ifdef Py_STATS | ||
| if (_py_stats) _py_stats->freelist_stats[list->size_class].frees++; | ||
| #endif | ||
| if (list->space) { | ||
| *((void **)ptr) = list->ptr; | ||
| list->ptr = ptr; | ||
| list->space--; | ||
| return; | ||
| } | ||
| #ifdef Py_STATS | ||
| if (_py_stats) _py_stats->freelist_stats[list->size_class].full++; | ||
| #endif | ||
| _PyFreeList_FreeToFull(list, ptr); | ||
iritkatriel marked this conversation as resolved.
Uh oh!There was an error while loading. Please reload this page. | ||
| } | ||
| static inline void | ||
| _PyFreeList_Init(_PyFreeList *list, int size_class, int size, int capacity) | ||
| { | ||
| list->ptr = NULL; | ||
| list->size = size; | ||
| #ifdef Py_STATS | ||
| list->size_class = size_class; | ||
| #endif | ||
| #if WITH_FREELISTS | ||
| list->space = list->capacity = capacity; | ||
| #else | ||
| _PyFreeList_Disable(list); | ||
| #endif | ||
| } | ||
| #ifdef __cplusplus | ||
| } | ||
| #endif | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -717,6 +717,64 @@ PyObject_Free(void *ptr) | ||
| # define LIKELY(value) (value) | ||
| #endif | ||
| void * | ||
| _PyFreeList_HalfFillAndAllocate(_PyFreeList *list) | ||
| { | ||
| assert(list->ptr == NULL); | ||
| if (list->capacity < 4) { | ||
| return PyObject_Malloc(list->size); | ||
| } | ||
| uint32_t i = 0; | ||
| for (; i < list->space>>1; i++) { | ||
| void* ptr = PyObject_Malloc(list->size); | ||
Member 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. Note for future PR: we should add the bulk allocate/free capability to the allocator. | ||
| if (ptr == NULL) { | ||
| break; | ||
| } | ||
| *((void**)ptr) = list->ptr; | ||
| list->ptr = ptr; | ||
| } | ||
| if (i == 0) { | ||
| return NULL; | ||
| } | ||
| void *result = list->ptr; | ||
| list->ptr = *((void **)result); | ||
| list->space -= (i-1); | ||
| return result; | ||
| } | ||
| void | ||
| _PyFreeList_Clear(_PyFreeList *list) | ||
| { | ||
| int space = 0; | ||
| void *head = list->ptr; | ||
| while (head) { | ||
| void *next = *((void**)head); | ||
| PyObject_Free(head); | ||
| head = next; | ||
| space++; | ||
| } | ||
| list->ptr = NULL; | ||
| list->space += space; | ||
| } | ||
| void | ||
| _PyFreeList_Disable(_PyFreeList *list) | ||
| { | ||
| list->space = list->capacity = 0; | ||
| } | ||
| void | ||
| _PyFreeList_FreeToFull(_PyFreeList *list, void *ptr) | ||
| { | ||
| assert(list->space == 0); | ||
| PyObject_Free(ptr); | ||
| if (list->ptr == NULL) { | ||
| return; | ||
| } | ||
| _PyFreeList_Clear(list); | ||
| } | ||
| #ifdef WITH_PYMALLOC | ||
| #ifdef WITH_VALGRIND | ||
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.