#include #include #include #include #include #include #include #include #define FIELD_ATTRIBUTE_STATIC 0x10 int memory_usage (MonoObject *this, GHashTable *visited) { int total = 0; MonoClass *class; gpointer iter = (gpointer) 0; MonoClassField *field; if (g_hash_table_lookup (visited, this)) return total; class = mono_object_get_class (this); g_hash_table_insert (visited, this, this); while ((field = mono_class_get_fields (class, &iter)) != NULL){ MonoType *ftype = mono_field_get_type (field); void *value; if ((ftype->attrs & FIELD_ATTRIBUTE_STATIC) != 0) continue; switch (ftype->type){ case MONO_TYPE_CLASS: case MONO_TYPE_OBJECT: mono_field_get_value (this, field, &value); if (value != NULL) total += memory_usage ((MonoObject *) value, visited); break; case MONO_TYPE_SZARRAY: { int len, i; mono_field_get_value (this, field, &value); len = mono_array_length ((MonoArray *)value); for (i = 0; i < len; i++){ MonoObject *item = mono_array_get ((MonoArray *) value, gpointer, i); if (item != NULL) total += memory_usage (item, visited); } } break; case MONO_TYPE_I4: case MONO_TYPE_I1: case MONO_TYPE_I2: case MONO_TYPE_U4: case MONO_TYPE_U2: case MONO_TYPE_U1: case MONO_TYPE_VOID: case MONO_TYPE_BOOLEAN: case MONO_TYPE_CHAR: /* ignore */ break; default: printf ("unhandled type: 0x%x\n", ftype->type); } } total += mono_class_instance_size (class); return total; } /* * Only returns data for instances, not for static fields, those might * be larger, or hold larger structures */ static int GetMemoryUsage (MonoObject *this) { GHashTable *visited = g_hash_table_new (NULL, NULL); int n; n = memory_usage (this, visited); g_hash_table_destroy (visited); return n; } static int installed = 0; void install_icall (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result) { if (installed) return; mono_add_internal_call ("Mono.ObjectServices.ObjectInspector::GetMemoryUsage", GetMemoryUsage); installed = 1; } void mono_profiler_startup (const char *desc) { mono_profiler_install_jit_end (install_icall); mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION); }