Commit 8f211be0 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add alloc stats for more things

Add alloc stats to the base Box::operator new(), which is where non-builtin
types get allocated.

Also add stats for non-Python allocations (typically, conservative memory);
turns out that we are allocating a lot of conservative memory (both in terms
of allocations but also in terms of allocation size) for dicts.
parent 2acc08e0
def f():
for i in xrange(10000000):
{}
f()
...@@ -518,10 +518,12 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems) ...@@ -518,10 +518,12 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
#if STAT_ALLOCATIONS #if STAT_ALLOCATIONS
#define ALLOC_STATS(cls) \ #define ALLOC_STATS(cls) \
if (cls->tp_name) { \
std::string per_name_alloc_name = "alloc." + std::string(cls->tp_name); \ std::string per_name_alloc_name = "alloc." + std::string(cls->tp_name); \
std::string per_name_allocsize_name = "allocsize." + std::string(cls->tp_name); \ std::string per_name_allocsize_name = "allocsize." + std::string(cls->tp_name); \
Stats::log(Stats::getStatId(per_name_alloc_name)); \ Stats::log(Stats::getStatId(per_name_alloc_name)); \
Stats::log(Stats::getStatId(per_name_allocsize_name), size); Stats::log(Stats::getStatId(per_name_allocsize_name), size); \
}
#define ALLOC_STATS_VAR(cls) \ #define ALLOC_STATS_VAR(cls) \
if (cls->tp_name) { \ if (cls->tp_name) { \
std::string per_name_alloc_name = "alloc." + std::string(cls->tp_name); \ std::string per_name_alloc_name = "alloc." + std::string(cls->tp_name); \
...@@ -550,7 +552,6 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems) ...@@ -550,7 +552,6 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
// asserts in the 1-arg operator new function: // asserts in the 1-arg operator new function:
#define DEFAULT_CLASS_SIMPLE(default_cls) \ #define DEFAULT_CLASS_SIMPLE(default_cls) \
void* operator new(size_t size, BoxedClass * cls) __attribute__((visibility("default"))) { \ void* operator new(size_t size, BoxedClass * cls) __attribute__((visibility("default"))) { \
ALLOC_STATS(cls); \
return Box::operator new(size, cls); \ return Box::operator new(size, cls); \
} \ } \
void* operator new(size_t size) __attribute__((visibility("default"))) { \ void* operator new(size_t size) __attribute__((visibility("default"))) { \
...@@ -601,7 +602,6 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems) ...@@ -601,7 +602,6 @@ extern "C" PyObject* PystonType_GenericAlloc(BoxedClass* cls, Py_ssize_t nitems)
} \ } \
\ \
void* operator new(size_t size, BoxedClass * cls, size_t nitems) __attribute__((visibility("default"))) { \ void* operator new(size_t size, BoxedClass * cls, size_t nitems) __attribute__((visibility("default"))) { \
ALLOC_STATS_VAR(default_cls) \
assert(cls->tp_itemsize == itemsize); \ assert(cls->tp_itemsize == itemsize); \
return BoxVar::operator new(size, cls, nitems); \ return BoxVar::operator new(size, cls, nitems); \
} \ } \
......
...@@ -28,7 +28,18 @@ namespace pyston { ...@@ -28,7 +28,18 @@ namespace pyston {
namespace gc { namespace gc {
static StatCounter gc_alloc_bytes("zzz_gc_alloc_bytes"); #if STAT_ALLOCATIONS
static StatCounter gc_alloc_bytes("gc_alloc_bytes");
static StatCounter gc_alloc_bytes_typed[] = {
StatCounter("gc_alloc_bytes_???"), //
StatCounter("gc_alloc_bytes_python"), //
StatCounter("gc_alloc_bytes_conservative"), //
StatCounter("gc_alloc_bytes_precise"), //
StatCounter("gc_alloc_bytes_untracked"), //
StatCounter("gc_alloc_bytes_hidden_class"), //
};
#endif
extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) { extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) {
STAT_TIMER(t0, "us_timer_gc_alloc"); STAT_TIMER(t0, "us_timer_gc_alloc");
size_t alloc_bytes = bytes + sizeof(GCAllocation); size_t alloc_bytes = bytes + sizeof(GCAllocation);
...@@ -94,6 +105,7 @@ extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) { ...@@ -94,6 +105,7 @@ extern "C" inline void* gc_alloc(size_t bytes, GCKind kind_id) {
#if STAT_ALLOCATIONS #if STAT_ALLOCATIONS
gc_alloc_bytes.log(bytes); gc_alloc_bytes.log(bytes);
gc_alloc_bytes_typed[(int)kind_id].log(bytes);
#endif #endif
return r; return r;
......
...@@ -111,9 +111,12 @@ static unsigned bytesAllocatedSinceCollection; ...@@ -111,9 +111,12 @@ static unsigned bytesAllocatedSinceCollection;
static __thread unsigned thread_bytesAllocatedSinceCollection; static __thread unsigned thread_bytesAllocatedSinceCollection;
#define ALLOCBYTES_PER_COLLECTION 10000000 #define ALLOCBYTES_PER_COLLECTION 10000000
static StatCounter gc_registered_bytes("gc_registered_bytes");
void registerGCManagedBytes(size_t bytes) { void registerGCManagedBytes(size_t bytes) {
thread_bytesAllocatedSinceCollection += bytes; thread_bytesAllocatedSinceCollection += bytes;
if (unlikely(thread_bytesAllocatedSinceCollection > ALLOCBYTES_PER_COLLECTION / 4)) { if (unlikely(thread_bytesAllocatedSinceCollection > ALLOCBYTES_PER_COLLECTION / 4)) {
gc_registered_bytes.log(thread_bytesAllocatedSinceCollection);
bytesAllocatedSinceCollection += thread_bytesAllocatedSinceCollection; bytesAllocatedSinceCollection += thread_bytesAllocatedSinceCollection;
thread_bytesAllocatedSinceCollection = 0; thread_bytesAllocatedSinceCollection = 0;
......
...@@ -180,6 +180,8 @@ extern "C" PyObject* _PyObject_New(PyTypeObject* tp) noexcept { ...@@ -180,6 +180,8 @@ extern "C" PyObject* _PyObject_New(PyTypeObject* tp) noexcept {
// Analogue of PyType_GenericNew // Analogue of PyType_GenericNew
void* BoxVar::operator new(size_t size, BoxedClass* cls, size_t nitems) { void* BoxVar::operator new(size_t size, BoxedClass* cls, size_t nitems) {
ALLOC_STATS_VAR(cls);
assert(cls); assert(cls);
ASSERT(cls->tp_basicsize >= size, "%s", cls->tp_name); ASSERT(cls->tp_basicsize >= size, "%s", cls->tp_name);
assert(cls->tp_itemsize > 0); assert(cls->tp_itemsize > 0);
...@@ -191,6 +193,8 @@ void* BoxVar::operator new(size_t size, BoxedClass* cls, size_t nitems) { ...@@ -191,6 +193,8 @@ void* BoxVar::operator new(size_t size, BoxedClass* cls, size_t nitems) {
} }
void* Box::operator new(size_t size, BoxedClass* cls) { void* Box::operator new(size_t size, BoxedClass* cls) {
ALLOC_STATS(cls);
assert(cls); assert(cls);
ASSERT(cls->tp_basicsize >= size, "%s", cls->tp_name); ASSERT(cls->tp_basicsize >= size, "%s", cls->tp_name);
assert(cls->tp_itemsize == 0); assert(cls->tp_itemsize == 0);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment