peps: a17ebebe52ca (original) (raw)

--- a/pep-0445.txt +++ b/pep-0445.txt @@ -40,18 +40,20 @@ Use cases: Proposal ======== -API changes ------------ +New functions and new structure +------------------------------- -* Add new GIL-free (no need to hold the GIL) memory allocator functions: +* Add a new GIL-free (no need to hold the GIL) memory allocator:

-* Add a new PyMemBlockAllocator structure:: +* Add a new PyMemAllocator structure:: typedef struct { /* user context passed as the first argument @@ -66,69 +68,70 @@ API changes /* release a memory block */ void (*free) (void *ctx, void *ptr);

-* Add new functions to get and set internal functions of

-* Add new functions to get and set internal functions of

+ +* Add new functions to get and set memory allocators: -* Add new functions to get and set internal functions of

- -* Add a new function to get and set the memory mapping allocator:

+* Add new functions to get and set the arena allocator used by

void* my_malloc(void *ctx, size_t size) { @@ -191,49 +205,49 @@ and 10 bytes per memory mapping:: free(ptr); }

PyMem_SetupDebugHooks(); } .. warning::

Use case 2: Replace Memory Allocator, override pymalloc -------------------------------------------------------- -If your allocator is optimized for allocation of small objects (less -than 512 bytes) with a short lifetime, pymalloc can be overriden -(replace PyObject_Malloc()). +If your allocator is optimized for allocations of objects smaller than +512 bytes with a short lifetime, pymalloc can be overriden (replace +PyObject_Malloc()). Dummy example wasting 2 bytes per memory block:: @@ -260,22 +274,22 @@ Dummy example wasting 2 bytes per memory void setup_custom_allocator(void) {

PyMem_SetupDebugHooks(); } .. warning::

@@ -285,15 +299,15 @@ Use case 3: Setup Allocator Hooks Example to setup hooks on all memory allocators:: struct {

@@ -302,7 +316,7 @@ Example to setup hooks on all memory all static void* hook_realloc(void *ctx, void *ptr, size_t new_size) {

@@ -312,7 +326,7 @@ Example to setup hooks on all memory all static void hook_free(void *ctx, void *ptr) {

@@ -320,7 +334,7 @@ Example to setup hooks on all memory all void setup_hooks(void) {

if (installed) @@ -330,27 +344,28 @@ Example to setup hooks on all memory all alloc.malloc = hook_malloc; alloc.realloc = hook_realloc; alloc.free = hook_free; -

+ alloc.ctx = &hook.obj;

.. note::

Performances @@ -369,32 +384,22 @@ The full reports are attached to the iss Alternatives ============ -Only one get/set function for block allocators ----------------------------------------------- - -Replace the 6 functions: +More specific functions to get/set memory allocators +---------------------------------------------------- -* void PyMem_GetRawAllocator(PyMemBlockAllocator *allocator) -* void PyMem_GetAllocator(PyMemBlockAllocator *allocator) -* void PyObject_GetAllocator(PyMemBlockAllocator *allocator) -* void PyMem_SetRawAllocator(PyMemBlockAllocator *allocator) -* void PyMem_SetAllocator(PyMemBlockAllocator *allocator) -* void PyObject_SetAllocator(PyMemBlockAllocator *allocator) +Replace the 2 functions: + +* void PyMem_GetAllocator(PyMemAllocatorDomain domain, PyMemAllocator *allocator) +* void PyMem_SetAllocator(PyMemAllocatorDomain domain, PyMemAllocator *allocator) -with 2 functions with an additional domain argument: - -* int PyMem_GetBlockAllocator(int domain, PyMemBlockAllocator *allocator) -* int PyMem_SetBlockAllocator(int domain, PyMemBlockAllocator *allocator) - -These functions return 0 on success, or -1 if the domain is unknown. +with: -where domain is one of these values: - -* PYALLOC_PYMEM -* PYALLOC_PYMEM_RAW -* PYALLOC_PYOBJECT - -Drawback: the caller has to check if the result is 0, or handle the error. +* void PyMem_GetRawAllocator(PyMemAllocator *allocator) +* void PyMem_GetAllocator(PyMemAllocator *allocator) +* void PyObject_GetAllocator(PyMemAllocator *allocator) +* void PyMem_SetRawAllocator(PyMemAllocator *allocator) +* void PyMem_SetAllocator(PyMemAllocator *allocator) +* void PyObject_SetAllocator(PyMemAllocator *allocator) Make PyMem_Malloc() reuse PyMem_RawMalloc() by default @@ -404,12 +409,6 @@ Make PyMem_Malloc() reuse PyMem_RawMallo calling PyMem_SetRawAllocator() would also also patch PyMem_Malloc() indirectly. -.. note:: -

Add a new PYDEBUGMALLOC environment variable -------------------------------------------- @@ -445,7 +444,7 @@ Define allocator functions as macros usi to get the C filename and line number of a memory allocation. Example of PyMem_Malloc macro with the modified -PyMemBlockAllocator structure:: +PyMemAllocator structure:: typedef struct { /* user context passed as the first argument @@ -463,7 +462,7 @@ Example of PyMem_Malloc macro with t /* release a memory block */ void (*free) (void *ctx, const char *filename, int lineno, void *ptr);

void* _PyMem_MallocTrace(const char *filename, int lineno, size_t size); @@ -485,12 +484,12 @@ changes add too much complexity for a li GIL-free PyMem_Malloc() ----------------------- -When Python is compiled in debug mode, PyMem_Malloc() calls -indirectly PyObject_Malloc() which requires the GIL to be held. -That's why PyMem_Malloc() must be called with the GIL held. +In Python 3.3, when Python is compiled in debug mode, PyMem_Malloc() +calls indirectly PyObject_Malloc() which requires the GIL to be +held. That's why PyMem_Malloc() must be called with the GIL held. -This PEP proposes to "fix" PyMem_Malloc() to make it always call -malloc(). So the "GIL must be held" restriction may be removed from +This PEP proposes changes PyMem_Malloc(): it now always call +malloc(). The "GIL must be held" restriction can be removed from PyMem_Malloc(). Allowing to call PyMem_Malloc() without holding the GIL might break @@ -516,9 +515,10 @@ Python call PyMem_Malloc() whereas t case, PyMem_Malloc() should be replaced with malloc() (or PyMem_RawMalloc()). -If an hook is used to the track memory usage, the malloc() memory -will not be seen. Remaining malloc() may allocate a lot of memory -and so would be missed in reports. +If an hook is used to the track memory usage, the memory allocated by +direct calls to malloc() will not be tracked. External libraries +like OpenSSL or bz2 should not call malloc() directly, so large +allocated will be included in memory usage reports. Use existing debug tools to analyze the memory @@ -545,8 +545,7 @@ GIL held allow to collect a lot of usefu Add msize() ----------- -Add another field to PyMemBlockAllocator and -PyMemMappingAllocator:: +Add another field to PyMemAllocator and PyObjectArenaAllocator:: size_t msize(void *ptr); @@ -574,6 +573,8 @@ It is likely for an allocator hook to be depending on the allocator. The context is a convenient way to reuse the same custom allocator or hook for different Python allocators. +In C++, the context can be used to pass this. + External libraries ================== @@ -589,6 +590,15 @@ Libraries used by Python: