summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Taylor <jtaylor.debian@googlemail.com>2017-04-03 12:42:37 +0200
committerJulian Taylor <jtaylor.debian@googlemail.com>2017-04-28 17:09:24 +0200
commit03534ec90dba2bcdcd649be64be57939dde4c6f5 (patch)
tree62b83ff8615e3b604e548e1040f76cd888377f15
parentd5657b9e29a8e00ad8e074bc32c15dec220d766f (diff)
downloadpython-numpy-03534ec90dba2bcdcd649be64be57939dde4c6f5.tar.gz
python-numpy-03534ec90dba2bcdcd649be64be57939dde4c6f5.tar.bz2
python-numpy-03534ec90dba2bcdcd649be64be57939dde4c6f5.zip
ENH: add support for python3.6 memory tracing
Python 3.6 added a private API for tracing arbitrary memory allocations so the tracemalloc module [0] can be used with numpy. closes gh-4663 [0] https://docs.python.org/3/library/tracemalloc.html
-rw-r--r--numpy/core/src/multiarray/alloc.c20
-rw-r--r--numpy/core/src/multiarray/alloc.h2
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c5
-rw-r--r--numpy/lib/__init__.py3
-rw-r--r--tools/allocation_tracking/README.md11
5 files changed, 40 insertions, 1 deletions
diff --git a/numpy/core/src/multiarray/alloc.c b/numpy/core/src/multiarray/alloc.c
index e5690ae4b..e145e3404 100644
--- a/numpy/core/src/multiarray/alloc.c
+++ b/numpy/core/src/multiarray/alloc.c
@@ -2,12 +2,25 @@
#include <Python.h>
#include "structmember.h"
+#if PY_VERSION_HEX >= 0x03060000
+#include <pymem.h>
+/* public api in 3.7 */
+#if PY_VERSION_HEX < 0x03070000
+#define PyTraceMalloc_Track _PyTraceMalloc_Track
+#define PyTraceMalloc_Untrack _PyTraceMalloc_Untrack
+#endif
+#else
+#define PyTraceMalloc_Track(...)
+#define PyTraceMalloc_Untrack(...)
+#endif
+
#define NPY_NO_DEPRECATED_API NPY_API_VERSION
#define _MULTIARRAYMODULE
#include <numpy/ndarraytypes.h>
#include "numpy/arrayobject.h"
#include <numpy/npy_common.h>
#include "npy_config.h"
+#include "alloc.h"
#include <assert.h>
@@ -192,6 +205,7 @@ PyDataMem_NEW(size_t size)
}
NPY_DISABLE_C_API
}
+ PyTraceMalloc_Track(NPY_TRACE_DOMAIN, (npy_uintp)result, size);
return result;
}
@@ -213,6 +227,7 @@ PyDataMem_NEW_ZEROED(size_t size, size_t elsize)
}
NPY_DISABLE_C_API
}
+ PyTraceMalloc_Track(NPY_TRACE_DOMAIN, (npy_uintp)result, size);
return result;
}
@@ -222,6 +237,7 @@ PyDataMem_NEW_ZEROED(size_t size, size_t elsize)
NPY_NO_EXPORT void
PyDataMem_FREE(void *ptr)
{
+ PyTraceMalloc_Untrack(NPY_TRACE_DOMAIN, (npy_uintp)ptr);
free(ptr);
if (_PyDataMem_eventhook != NULL) {
NPY_ALLOW_C_API_DEF
@@ -243,6 +259,10 @@ PyDataMem_RENEW(void *ptr, size_t size)
void *result;
result = realloc(ptr, size);
+ if (result != ptr) {
+ PyTraceMalloc_Untrack(NPY_TRACE_DOMAIN, (npy_uintp)ptr);
+ }
+ PyTraceMalloc_Track(NPY_TRACE_DOMAIN, (npy_uintp)result, size);
if (_PyDataMem_eventhook != NULL) {
NPY_ALLOW_C_API_DEF
NPY_ALLOW_C_API
diff --git a/numpy/core/src/multiarray/alloc.h b/numpy/core/src/multiarray/alloc.h
index 8f6b167d0..39eb99544 100644
--- a/numpy/core/src/multiarray/alloc.h
+++ b/numpy/core/src/multiarray/alloc.h
@@ -4,6 +4,8 @@
#define _MULTIARRAYMODULE
#include <numpy/ndarraytypes.h>
+#define NPY_TRACE_DOMAIN 389047
+
NPY_NO_EXPORT void *
npy_alloc_cache(npy_uintp sz);
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index 73ba8c5c4..b6b134f2d 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -60,6 +60,7 @@ NPY_NO_EXPORT int NPY_NUMUSERTYPES = 0;
#include "templ_common.h" /* for npy_mul_with_overflow_intp */
#include "compiled_base.h"
#include "mem_overlap.h"
+#include "alloc.h"
#include "get_attr_string.h"
@@ -4624,6 +4625,10 @@ PyMODINIT_FUNC initmultiarray(void) {
*/
PyDict_SetItemString (d, "error", PyExc_Exception);
+ s = PyInt_FromLong(NPY_TRACE_DOMAIN);
+ PyDict_SetItemString(d, "tracemalloc_domain", s);
+ Py_DECREF(s);
+
s = PyUString_FromString("3.1");
PyDict_SetItemString(d, "__version__", s);
Py_DECREF(s);
diff --git a/numpy/lib/__init__.py b/numpy/lib/__init__.py
index 4cdb76b20..847a3e896 100644
--- a/numpy/lib/__init__.py
+++ b/numpy/lib/__init__.py
@@ -25,8 +25,9 @@ from .financial import *
from .arrayterator import Arrayterator
from .arraypad import *
from ._version import *
+from numpy.core.multiarray import tracemalloc_domain
-__all__ = ['emath', 'math']
+__all__ = ['emath', 'math', 'tracemalloc_domain']
__all__ += type_check.__all__
__all__ += index_tricks.__all__
__all__ += function_base.__all__
diff --git a/tools/allocation_tracking/README.md b/tools/allocation_tracking/README.md
new file mode 100644
index 000000000..fd4f2c871
--- /dev/null
+++ b/tools/allocation_tracking/README.md
@@ -0,0 +1,11 @@
+Example for using the `PyDataMem_SetEventHook` to track allocations inside numpy.
+
+`alloc_hook.pyx` implements a hook in Cython that calls back into a python
+function. `track_allocations.py` uses it for a simple listing of allocations.
+It can be built with the `setup.py` file in this folder.
+
+Note that since Python 3.6 the builtin tracemalloc module can be used to
+track allocations inside numpy.
+Numpy places its CPU memory allocations into the `np.lib.tracemalloc_domain`
+domain.
+See https://docs.python.org/3/library/tracemalloc.html.