PEP 445: cleanup and inline examples

This commit is contained in:
Victor Stinner 2013-06-18 01:30:05 +02:00
parent e2168ebe67
commit c3ae1b4d51
4 changed files with 107 additions and 239 deletions

View File

@ -80,114 +80,178 @@ API changes
Examples
========
Use case 1: replace memory allocators, keeping pymalloc
-------------------------------------------------------
Use case 1: Replace Memory Allocators, keep pymalloc
----------------------------------------------------
Setup your custom memory allocators, keeping pymalloc::
/* global variable, don't use a variable allocated on the stack! */
int magic = 42;
#include <stdlib.h>
int my_malloc(void *ctx, size_t size);
int my_realloc(void *ctx, void *ptr, size_t new_size);
void my_free(void *ctx, void *ptr);
int alloc_padding = 2;
int arena_padding = 10;
int my_alloc_arena(void *ctx, size_t size);
int my_free_arena(void *ctx, void *ptr, size_t size);
void* my_malloc(void *ctx, size_t size)
{
int padding = *(int *)ctx;
return malloc(size + padding);
}
void* my_realloc(void *ctx, void *ptr, size_t new_size)
{
int padding = *(int *)ctx;
return realloc(ptr, new_size + padding);
}
void my_free(void *ctx, void *ptr)
{
free(ptr);
}
void* my_alloc_arena(void *ctx, size_t size)
{
int padding = *(int *)ctx;
return malloc(size + padding);
}
void my_free_arena(void *ctx, void *ptr, size_t size)
{
free(ptr);
}
void setup_custom_allocators(void)
{
PyMemAllocators alloc;
alloc.ctx = &magic;
alloc.ctx = &alloc_padding;
alloc.malloc = my_malloc;
alloc.realloc = my_realloc;
alloc.free = my_free;
PyMem_SetRawAllocators(&alloc);
PyMem_SetAllocators(&alloc);
_PyObject_SetArenaAllocators(&magic, my_alloc_arena, my_free_arena);
_PyObject_SetArenaAllocators(&arena_padding,
my_alloc_arena, my_free_arena);
PyMem_SetupDebugHooks();
}
.. warning::
Remove call ``PyMem_SetRawAllocators(&alloc);`` if the new allocators are
not thread-safe.
Full example:
`replace_allocs.c <http://hg.python.org/peps/file/tip/pep-0445/replace_allocs.c>`_.
Remove the call ``PyMem_SetRawAllocators(&alloc);`` if the new allocators
are not thread-safe.
Use case 2: replace memory allocators, overriding pymalloc
Use case 2: Replace Memory Allocators, overriding pymalloc
----------------------------------------------------------
If your allocator is optimized for allocation of small objects (less than 512
bytes) with a short liftime, you can replace override pymalloc (replace
``PyObject_Malloc()``). Example::
/* global variable, don't use a variable allocated on the stack! */
int magic = 42;
#include <stdlib.h>
int my_malloc(void *ctx, size_t size);
int my_realloc(void *ctx, void *ptr, size_t new_size);
void my_free(void *ctx, void *ptr);
int padding = 2;
void* my_malloc(void *ctx, size_t size)
{
int padding = *(int *)ctx;
return malloc(size + padding);
}
void* my_realloc(void *ctx, void *ptr, size_t new_size)
{
int padding = *(int *)ctx;
return realloc(ptr, new_size + padding);
}
void my_free(void *ctx, void *ptr)
{
free(ptr);
}
void setup_custom_allocators(void)
{
PyMemAllocators alloc;
alloc.ctx = &magic;
alloc.ctx = &padding;
alloc.malloc = my_malloc;
alloc.realloc = my_realloc;
alloc.free = my_free;
PyMem_SetRawAllocators(&alloc);
PyMem_SetAllocators(&alloc);
PyObject_SetAllocators(&areana);
PyObject_SetAllocators(&alloc);
PyMem_SetupDebugHooks();
}
Full example:
`replace_pymalloc.c <http://hg.python.org/peps/file/tip/pep-0445/replace_pymalloc.c>`_.
.. warning::
Remove the call ``PyMem_SetRawAllocators(&alloc);`` if the new allocators
are not thread-safe.
Use case 3: hook allocators
---------------------------
Use case 3: Setup Allocator Hooks
---------------------------------
Setup hooks on memory allocators::
/* global variable, don't use a variable allocated on the stack! */
struct {
PyMemAllocators pymem;
PyMemAllocators pymem_raw;
PyMemAllocators pyobj;
int magic;
/* ... */
} hook;
int hook_malloc(void *ctx, size_t size);
int hook_realloc(void *ctx, void *ptr, size_t new_size);
void hook_free(void *ctx, void *ptr);
static void* hook_malloc(void *ctx, size_t size)
{
PyMemAllocators *alloc = (PyMemAllocators *)ctx;
/* ... */
ptr = alloc->malloc(alloc->ctx, size);
/* ... */
return ptr;
}
/* Must be called before the first allocation, or hook_realloc() and
hook_free() will crash */
void setup_custom_allocators(void)
static void* hook_realloc(void *ctx, void *ptr, size_t new_size)
{
PyMemAllocators *alloc = (PyMemAllocators *)ctx;
void *ptr2;
/* ... */
ptr2 = alloc->realloc(alloc->ctx, ptr, new_size);
/* ... */
return ptr2;
}
static void hook_free(void *ctx, void *ptr)
{
PyMemAllocators *alloc = (PyMemAllocators *)ctx;
/* ... */
alloc->free(alloc->ctx, ptr);
/* ... */
}
void setup_hooks(void)
{
PyMemAllocators alloc;
static int registered = 0;
if (registered)
return;
registered = 1;
alloc.ctx = &magic;
alloc.malloc = hook_malloc;
alloc.realloc = hook_realloc;
alloc.free = hook_free;
PyMem_GetRawAllocators(&alloc.pymem_raw);
alloc.ctx = &alloc.pymem_raw;
PyMem_GetRawAllocators(&hook.pymem_raw);
alloc.ctx = &hook.pymem_raw;
PyMem_SetRawAllocators(&alloc);
PyMem_GetAllocators(&alloc.pymem);
alloc.ctx = &alloc.pymem;
PyMem_GetAllocators(&hook.pymem);
alloc.ctx = &hook.pymem;
PyMem_SetAllocators(&alloc);
PyObject_GetAllocators(&alloc.pyobj);
alloc.ctx = &alloc.pyobj;
PyObject_GetAllocators(&hook.pyobj);
alloc.ctx = &hook.pyobj;
PyObject_SetAllocators(&alloc);
}
@ -195,10 +259,6 @@ Setup hooks on memory allocators::
No need to call ``PyMem_SetupDebugHooks()``: it is already installed by
default.
Full example tracking memory usage:
`alloc_hooks.c <http://hg.python.org/peps/file/tip/pep-0445/alloc_hooks.c>`_.
Performances
============

View File

@ -1,114 +0,0 @@
/* global variable, don't use a variable allocated on the stack! */
struct {
PyMemAllocators pymem;
PyMemAllocators pymem_raw;
PyMemAllocators pyobj;
size_t allocated;
} hook;
/* read_size_t() and write_size_t() are not needed if malloc() and realloc()
always return a pointer aligned to sizeof(size_t) bytes */
static size_t read_size_t(const void *p)
{
const unsigned char *q = (const unsigned char *)p;
size_t result = *q++;
int i;
for (i = SST; --i > 0; ++q)
result = (result << 8) | *q;
return result;
}
static void write_size_t(void *p, size_t n)
{
unsigned char *q = (unsigned char *)p + SST - 1;
int i;
for (i = SST; --i >= 0; --q) {
*q = (unsigned char)(n & 0xff);
n >>= 8;
}
}
static int hook_malloc(void *ctx, size_t size)
{
PyMemAllocators *alloc;
char *ptr;
size += sizeof(size_t);
ptr = alloc->malloc(size);
if (ptr != NULL) {
write_size_t(ptr, size);
ptr += sizeof(size_t);
allocated += size;
}
return ptr;
}
static int hook_realloc(void *ctx, void *void_ptr, size_t new_size)
{
PyMemAllocators *alloc;
char *ptr, *ptr2;
size_t old_size;
ptr = void_ptr;
if (ptr) {
ptr -= sizeof(size_t);
old_size = read_size_t(ptr);
}
else {
old_size = 0;
}
ptr2 = alloc->realloc(ptr, size);
if (ptr2 != NULL) {
write_size_t(ptr2, size);
ptr2 += sizeof(size_t);
allocated -= old_size;
allocated += new_size;
}
return ptr2;
}
static void hook_free(void *ctx, void *void_ptr)
{
PyMemAllocators *alloc;
char *ptr;
size_t size;
ptr = void_ptr;
if (!ptr)
return;
ptr -= sizeof(size_t);
size = read_size_t(ptr);
alloc->free(ptr);
allocated -= size;
}
/* Must be called before the first allocation, or hook_realloc() and
hook_free() will crash */
void setup_custom_allocators(void)
{
PyMemAllocators alloc;
alloc.malloc = my_malloc;
alloc.realloc = my_realloc;
alloc.free = my_free;
/* disabled: the hook is not thread-safe */
#if 0
PyMem_GetRawAllocators(&alloc.pymem_raw);
alloc.ctx = &alloc.pymem_raw;
PyMem_SetRawAllocators(&alloc);
#endif
PyMem_GetAllocators(&alloc.pymem);
alloc.ctx = &alloc.pymem;
PyMem_SetAllocators(&alloc);
PyObject_GetAllocators(&alloc.pyobj);
alloc.ctx = &alloc.pyobj;
PyObject_SetAllocators(&alloc);
}

View File

@ -1,44 +0,0 @@
#include <stdlib.h>
/* global variable, don't use a variable allocated on the stack! */
int magic = 42;
int my_malloc(void *ctx, size_t size)
{
return malloc(size);
}
int my_realloc(void *ctx, void *ptr, size_t new_size)
{
return realloc(ptr, new_size);
}
void my_free(void *ctx, void *ptr)
{
free(ptr);
}
int my_alloc_arena(void *ctx, size_t size)
{
return malloc(size);
}
int my_free_arena(void *ctx, void *ptr, size_t size)
{
free(ptr);
}
void setup_custom_allocators(void)
{
PyMemAllocators alloc;
alloc.ctx = &magic;
alloc.malloc = my_malloc;
alloc.realloc = my_realloc;
alloc.free = my_free;
PyMem_SetRawAllocators(&alloc);
PyMem_SetAllocators(&alloc);
_PyObject_SetArenaAllocators(&magic, my_alloc_arena, my_free_arena);
PyMem_SetupDebugHooks();
}

View File

@ -1,34 +0,0 @@
#include <stdlib.h>
/* global variable, don't use a variable allocated on the stack! */
int magic = 42;
int my_malloc(void *ctx, size_t size)
{
return malloc(size);
}
int my_realloc(void *ctx, void *ptr, size_t new_size)
{
return realloc(ptr, new_size);
}
void my_free(void *ctx, void *ptr)
{
free(ptr);
}
void setup_custom_allocators(void)
{
PyMemAllocators alloc;
alloc.ctx = &magic;
alloc.malloc = my_malloc;
alloc.realloc = my_realloc;
alloc.free = my_free;
PyMem_SetRawAllocators(&alloc);
PyMem_SetAllocators(&alloc);
PyObject_SetAllocators(&areana);
PyMem_SetupDebugHooks();
}