Add 'size' sample
[mono.git] / samples / size / size.c
1 #include <glib.h>
2 #include <mono/jit/jit.h>
3 #include <mono/metadata/environment.h>
4 #include <mono/metadata/profiler.h>
5 #include <mono/metadata/tokentype.h>
6 #include <mono/metadata/debug-helpers.h>
7 #include <mono/metadata/assembly.h>
8 #include <string.h>
9
10 #define FIELD_ATTRIBUTE_STATIC 0x10
11
12 int
13 memory_usage (MonoObject *this, GHashTable *visited)
14 {
15         int total = 0;
16         MonoClass *class;
17         gpointer iter = (gpointer) 0;
18         MonoClassField *field;
19         
20         if (g_hash_table_lookup (visited, this))
21                 return total;
22
23         class = mono_object_get_class (this);
24         
25         g_hash_table_insert (visited, this, this);
26
27         while ((field = mono_class_get_fields (class, &iter)) != NULL){
28                 MonoType *ftype = mono_field_get_type (field);
29                 void *value;
30
31                 if ((ftype->attrs & FIELD_ATTRIBUTE_STATIC) != 0)
32                         continue;
33
34                 switch (ftype->type){
35                 case MONO_TYPE_CLASS: 
36                 case MONO_TYPE_OBJECT:
37                         mono_field_get_value (this, field, &value);
38
39                         if (value != NULL)
40                                 total += memory_usage ((MonoObject *) value, visited);
41                         break;
42
43                 case MONO_TYPE_SZARRAY:
44                         printf ("implement me\n");
45                         break;
46                         
47                 case MONO_TYPE_I4:
48                 case MONO_TYPE_I1:
49                 case MONO_TYPE_I2:
50                 case MONO_TYPE_U4:
51                 case MONO_TYPE_U2:
52                 case MONO_TYPE_U1:
53                 case MONO_TYPE_VOID:
54                 case MONO_TYPE_BOOLEAN:
55                 case MONO_TYPE_CHAR:
56                         /* ignore */
57                         break;
58                 default:
59                         printf ("unhandled type: 0x%x\n", ftype->type);
60                 }
61         }
62         
63         total += mono_class_instance_size (class);
64
65         return total;
66 }
67
68 /*
69  * Only returns data for instances, not for static fields, those might
70  * be larger, or hold larger structures
71  */
72 static int
73 GetMemoryUsage (MonoObject *this)
74 {
75         GHashTable *visited = g_hash_table_new (NULL, NULL);
76         int n;
77         
78         n = memory_usage (this, visited);
79
80         g_hash_table_destroy (visited);
81         
82         return n;
83 }
84
85 static int installed = 0;
86
87 void install_icall (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result)
88 {
89         if (installed)
90                 return;
91
92         mono_add_internal_call ("Mono.ObjectServices.ObjectInspector::GetMemoryUsage", GetMemoryUsage);
93         installed = 1;
94 }
95
96 void
97 mono_profiler_startup (const char *desc)
98 {
99         mono_profiler_install_jit_end (install_icall);
100         mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
101 }