[Python-checkins] r50920 - in python/branches/bcannon-sandboxing: Include/objimpl.h Include/pymem.h Objects/trackedmalloc.c Python/sysmodule.c

brett.cannon python-checkins at python.org
Sat Jul 29 01:45:00 CEST 2006


Author: brett.cannon
Date: Sat Jul 29 01:44:59 2006
New Revision: 50920

Modified:
   python/branches/bcannon-sandboxing/Include/objimpl.h
   python/branches/bcannon-sandboxing/Include/pymem.h
   python/branches/bcannon-sandboxing/Objects/trackedmalloc.c
   python/branches/bcannon-sandboxing/Python/sysmodule.c
Log:
Add tracking at the type level.

Uses a linked list to store types since easy to do in pure C and thus minimize
bootstrapping issues of using Python objects when tracking memory allocation.
Plus the number of types created during the lifetime of a Python process is
actually rather small.


Modified: python/branches/bcannon-sandboxing/Include/objimpl.h
==============================================================================
--- python/branches/bcannon-sandboxing/Include/objimpl.h	(original)
+++ python/branches/bcannon-sandboxing/Include/objimpl.h	Sat Jul 29 01:44:59 2006
@@ -95,6 +95,7 @@
    the raw memory.
 */
 PyAPI_DATA(unsigned long) Py_ProcessMemUsage;
+PyAPI_FUNC(PyObject *) Py_MemoryUsage(PyObject *, PyObject *);
 PyAPI_FUNC(int) PyMalloc_ManagesMemory(void *);
 PyAPI_FUNC(size_t) PyMalloc_AllocatedSize(void *);
 PyAPI_FUNC(void *) PyObject_Malloc(size_t);

Modified: python/branches/bcannon-sandboxing/Include/pymem.h
==============================================================================
--- python/branches/bcannon-sandboxing/Include/pymem.h	(original)
+++ python/branches/bcannon-sandboxing/Include/pymem.h	Sat Jul 29 01:44:59 2006
@@ -61,12 +61,6 @@
 #define PyMem_REALLOC		PyObject_REALLOC
 #define PyMem_FREE		PyObject_FREE
 
-#elif define (Py_TRACK_MEMORY)
-
-#define PyMem_MALLOC(size)	PyObject_T_MALLOC("", size)
-#define PyMem_REALLOC(size)	PyObject_T_REALLOC("", size)
-#define PyMem_FREE(size)	PyObject_T_FREE("", size)
-
 #else	/* ! PYMALLOC_DEBUG */
 
 /* PyMem_MALLOC(0) means malloc(1). Some systems would return NULL

Modified: python/branches/bcannon-sandboxing/Objects/trackedmalloc.c
==============================================================================
--- python/branches/bcannon-sandboxing/Objects/trackedmalloc.c	(original)
+++ python/branches/bcannon-sandboxing/Objects/trackedmalloc.c	Sat Jul 29 01:44:59 2006
@@ -26,9 +26,9 @@
     * PyObject_GC_Resize()
 	Uses PyObject_T_MALLOC()
     * PyMem_Malloc()/PyMem_Realloc()/PyMem_Free()
-	Uses PyMem_MALLOC(), etc.
+	XXX
     * PyMem_MALLOC()/PyMem_REALLOC()/PyMem_FREE()
-	Change to PyObject_T_*("", size)
+	XXX
     * malloc()/realloc()/free()
 	XXX
 
@@ -52,6 +52,72 @@
 
 static const char *UNKNOWN_WHAT = "<unknown>";
 
+struct mem_item {
+    struct mem_item *next;
+    const char *type;
+    unsigned long using;
+};
+
+static struct mem_item mem_sentinel = {NULL, NULL, 0};
+static struct mem_item *mem_head  = &mem_sentinel;
+static Py_ssize_t mem_item_count = 0;
+
+
+PyObject *
+Py_MemoryUsage(PyObject *self, PyObject *ignore)
+{
+    struct mem_item *cur_mem = mem_head;
+    PyObject *mem_dict = PyDict_New();
+    Py_ssize_t x = 0;
+    int int_result = 0;
+
+    if (!mem_dict)
+	return NULL;
+
+    for (x=0; x < mem_item_count; x+=1) {
+	cur_mem = cur_mem->next;
+	PyObject *long_obj = PyLong_FromUnsignedLong(cur_mem->using);
+	if (!long_obj)
+	    return NULL;
+	int_result = PyDict_SetItemString(mem_dict, cur_mem->type, long_obj);
+	Py_DECREF(long_obj);
+	
+	if (int_result < 0)
+	    return NULL;
+    }
+
+    return mem_dict;
+}
+
+/* XXX remove entries where memory usage is zero? */
+static struct mem_item *
+find_mem_entry(const char *what)
+{
+    struct mem_item *cur_mem = mem_head;
+
+    what = what ? what : UNKNOWN_WHAT;
+
+    while (cur_mem->next) {
+	cur_mem = cur_mem->next;
+
+	if (strcmp(what, cur_mem->type) == 0)
+	    return cur_mem;
+    }
+
+    cur_mem->next = malloc(sizeof(struct mem_item));
+    cur_mem = cur_mem->next;
+
+    if (!cur_mem)
+	return NULL;
+
+    mem_item_count += 1;
+
+    cur_mem->next = NULL;
+    cur_mem->type = what;  /* XXX memcpy? */
+    cur_mem->using = 0;
+
+    return cur_mem;
+}
 
 /*
    Track an anonymous chunk of memory.
@@ -59,8 +125,13 @@
 int
 PyObject_TrackMemory(const char *what, size_t nbytes)
 {
-    what = what ? what : UNKNOWN_WHAT;
+    struct mem_item *mem_entry = find_mem_entry(what);
 
+    if (!mem_entry)
+	return 0;
+
+    /* XXX check for overflow. */
+    mem_entry->using += nbytes;
     Py_ProcessMemUsage += nbytes;
 
     return 1;
@@ -72,8 +143,13 @@
 int
 PyObject_UntrackMemory(const char *what, size_t nbytes)
 {
-    what = what ? what : UNKNOWN_WHAT;
+    struct mem_item *mem_entry = find_mem_entry(what);
+
+    if (!mem_entry)
+	return 0;
 
+    /* XXX check for hitting < 0. */
+    mem_entry->using -= nbytes;
     Py_ProcessMemUsage -= nbytes;
 
     return 1;

Modified: python/branches/bcannon-sandboxing/Python/sysmodule.c
==============================================================================
--- python/branches/bcannon-sandboxing/Python/sysmodule.c	(original)
+++ python/branches/bcannon-sandboxing/Python/sysmodule.c	Sat Jul 29 01:44:59 2006
@@ -782,6 +782,7 @@
 #endif
 	{"settrace",	sys_settrace, METH_O, settrace_doc},
 	{"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc},
+	{"memoryusage", Py_MemoryUsage, METH_NOARGS, "XXX"},
 	{NULL,		NULL}		/* sentinel */
 };
 


More information about the Python-checkins mailing list