2005-09-27 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / metadata / profiler.c
index c0acec23445f83ca6ffcb0404cc4a34d250a22f4..a953bde607e5c7b09efa9bfd27903ed90dc7cec2 100644 (file)
@@ -5,6 +5,7 @@
 #include "mono/metadata/mono-debug.h"
 #include "mono/metadata/class-internals.h"
 #include "mono/metadata/domain-internals.h"
+#include "mono/metadata/gc-internal.h"
 #include "mono/io-layer/io-layer.h"
 #include <string.h>
 #include <sys/time.h>
@@ -50,6 +51,11 @@ static MonoProfileCoverageFilterFunc coverage_filter_cb;
 
 static MonoProfileFunc shutdown_callback;
 
+static MonoProfileGCFunc        gc_event;
+static MonoProfileGCResizeFunc  gc_heap_resize;
+
+#define mono_profiler_coverage_lock() EnterCriticalSection (&profiler_coverage_mutex)
+#define mono_profiler_coverage_unlock() LeaveCriticalSection (&profiler_coverage_mutex)
 static CRITICAL_SECTION profiler_coverage_mutex;
 
 /* this is directly accessible to other mono libs. */
@@ -213,14 +219,14 @@ mono_profiler_stat_hit (guchar *ip, void *context)
 }
 
 void
-mono_profiler_thread_start (guint32 tid)
+mono_profiler_thread_start (gsize tid)
 {
        if ((mono_profiler_events & MONO_PROFILE_THREADS) && thread_start)
                thread_start (current_profiler, tid);
 }
 
 void 
-mono_profiler_thread_end (guint32 tid)
+mono_profiler_thread_end (gsize tid)
 {
        if ((mono_profiler_events & MONO_PROFILE_THREADS) && thread_end)
                thread_end (current_profiler, tid);
@@ -357,6 +363,28 @@ mono_profiler_shutdown (void)
                shutdown_callback (current_profiler);
 }
 
+void
+mono_profiler_gc_heap_resize (gint64 new_size)
+{
+       if ((mono_profiler_events & MONO_PROFILE_GC) && gc_heap_resize)
+               gc_heap_resize (current_profiler, new_size);
+}
+
+void
+mono_profiler_gc_event (MonoGCEvent event, int generation)
+{
+       if ((mono_profiler_events & MONO_PROFILE_GC) && gc_event)
+               gc_event (current_profiler, event, generation);
+}
+
+void
+mono_profiler_install_gc (MonoProfileGCFunc callback, MonoProfileGCResizeFunc heap_resize_callback)
+{
+       mono_gc_enable_events ();
+       gc_event = callback;
+       gc_heap_resize = heap_resize_callback;
+}
+
 static GHashTable *coverage_hash = NULL;
 
 MonoProfileCoverageInfo* 
@@ -368,7 +396,7 @@ mono_profiler_coverage_alloc (MonoMethod *method, int entries)
                if (! (*coverage_filter_cb) (current_profiler, method))
                        return NULL;
 
-       EnterCriticalSection (&profiler_coverage_mutex);
+       mono_profiler_coverage_lock ();
        if (!coverage_hash)
                coverage_hash = g_hash_table_new (NULL, NULL);
 
@@ -377,7 +405,7 @@ mono_profiler_coverage_alloc (MonoMethod *method, int entries)
        res->entries = entries;
 
        g_hash_table_insert (coverage_hash, method, res);
-       LeaveCriticalSection (&profiler_coverage_mutex);
+       mono_profiler_coverage_unlock ();
 
        return res;
 }
@@ -388,9 +416,9 @@ mono_profiler_coverage_free (MonoMethod *method)
 {
        MonoProfileCoverageInfo* info;
 
-       EnterCriticalSection (&profiler_coverage_mutex);
+       mono_profiler_coverage_lock ();
        if (!coverage_hash) {
-               LeaveCriticalSection (&profiler_coverage_mutex);
+               mono_profiler_coverage_unlock ();
                return;
        }
 
@@ -399,7 +427,7 @@ mono_profiler_coverage_free (MonoMethod *method)
                g_free (info);
                g_hash_table_remove (coverage_hash, method);
        }
-       LeaveCriticalSection (&profiler_coverage_mutex);
+       mono_profiler_coverage_unlock ();
 }
 
 void 
@@ -412,9 +440,9 @@ mono_profiler_coverage_get (MonoProfiler *prof, MonoMethod *method, MonoProfileC
        MonoMethodHeader *header;
        MonoProfileCoverageEntry entry;
 
-       EnterCriticalSection (&profiler_coverage_mutex);
+       mono_profiler_coverage_lock ();
        info = g_hash_table_lookup (coverage_hash, method);
-       LeaveCriticalSection (&profiler_coverage_mutex);
+       mono_profiler_coverage_unlock ();
 
        if (!info)
                return;
@@ -677,7 +705,7 @@ method_get_name (MonoMethod* method)
 {
        char *sig, *res;
        
-       sig = mono_signature_get_desc (method->signature, FALSE);
+       sig = mono_signature_get_desc (mono_method_signature (method), FALSE);
        res = g_strdup_printf ("%s.%s::%s(%s)", method->klass->name_space, method->klass->name,
                method->name, sig);
        g_free (sig);
@@ -704,7 +732,7 @@ output_profile (GList *funcs)
                m = method_get_name (p->method);
                printf ("########################\n");
                printf ("% 8.3f ", (double) (p->total * 1000));
-               printf ("%7llu ", p->count);
+               printf ("%7llu ", (unsigned long long)p->count);
                printf ("% 8.3f ", (double) (p->total * 1000)/(double)p->count);
                printf ("  %s\n", m);
 
@@ -712,7 +740,7 @@ output_profile (GList *funcs)
                /* callers */
                output_callers (p);
        }
-       printf ("Total number of calls: %lld\n", total_calls);
+       printf ("Total number of calls: %lld\n", (long long)total_calls);
 }
 
 typedef struct {
@@ -1010,13 +1038,7 @@ simple_allocation (MonoProfiler *prof, MonoObject *obj, MonoClass *klass)
                profile_info->alloc_info = tmp;
        }
        tmp->count++;
-       if (klass == mono_defaults.string_class) {
-               tmp->mem += sizeof (MonoString) + 2 * mono_string_length ((MonoString*)obj) + 2;
-       } else if (klass->parent == mono_defaults.array_class) {
-               tmp->mem += sizeof (MonoArray) + mono_array_element_size (klass) * mono_array_length ((MonoArray*)obj);
-       } else {
-               tmp->mem += mono_class_instance_size (klass);
-       }
+       tmp->mem += mono_object_get_size (obj);
 }
 
 static void
@@ -1081,7 +1103,7 @@ struct Addr2LineData {
        FILE *pipein;
        FILE *pipeout;
        char *binary;
-       GPid child_pid;
+       int child_pid;
 };
 
 static Addr2LineData *addr2line_pipes = NULL;
@@ -1099,7 +1121,7 @@ try_addr2line (const char* binary, gpointer ip)
        }
        if (!addr2line) {
                const char *addr_argv[] = {"addr2line", "-f", "-e", binary, NULL};
-               GPid child_pid;
+               int child_pid;
                int ch_in, ch_out;
                if (!g_spawn_async_with_pipes (NULL, (char**)addr_argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
                                &child_pid, &ch_in, &ch_out, NULL, NULL)) {
@@ -1138,8 +1160,9 @@ stat_prof_report (void)
        char *mn;
        gpointer ip;
        GList *tmp, *sorted = NULL;
+       int pcount = ++ prof_counts;
 
-       prof_counts ++;
+       prof_counts = MAX_PROF_SAMPLES;
        for (i = 0; i < count; ++i) {
                ip = prof_addresses [i];
                ji = mono_jit_info_table_find (mono_domain_get (), ip);
@@ -1182,7 +1205,7 @@ stat_prof_report (void)
                if (c > 1)
                        g_free (mn);
        }
-       g_print ("prof counts: total/unmanaged: %d/%d\n", prof_counts, prof_ucounts);
+       g_print ("prof counts: total/unmanaged: %d/%d\n", pcount, prof_ucounts);
        g_hash_table_foreach (prof_table, (GHFunc)prof_foreach, &sorted);
        for (tmp = sorted; tmp; tmp = tmp->next) {
                double perc;
@@ -1232,6 +1255,7 @@ simple_shutdown (MonoProfiler *prof)
        g_list_free (profile);
 
        g_free (prof_addresses);
+       prof_addresses = NULL;
        g_hash_table_destroy (prof_table);
 }
 
@@ -1240,16 +1264,19 @@ mono_profiler_install_simple (const char *desc)
 {
        MonoProfiler *prof;
        gchar **args, **ptr;
-       MonoProfileFlags flags = MONO_PROFILE_JIT_COMPILATION;
+       MonoProfileFlags flags = 0;
 
        MONO_TIMER_STARTUP;
 
+       if (!desc)
+               desc = "alloc,time,jit";
+
        if (desc) {
                /* Parse options */
                if (strstr (desc, ":"))
                        desc = strstr (desc, ":") + 1;
                else
-                       desc = "alloc,time";
+                       desc = "alloc,time,jit";
                args = g_strsplit (desc, ",", -1);
 
                for (ptr = args; ptr && *ptr; ptr++) {
@@ -1261,6 +1288,8 @@ mono_profiler_install_simple (const char *desc)
                                flags |= MONO_PROFILE_ALLOCATIONS;
                        else if (!strcmp (arg, "stat"))
                                flags |= MONO_PROFILE_STATISTICAL | MONO_PROFILE_APPDOMAIN_EVENTS;
+                       else if (!strcmp (arg, "jit"))
+                               flags |= MONO_PROFILE_JIT_COMPILATION;
                        else {
                                fprintf (stderr, "profiler : Unknown argument '%s'.\n", arg);
                                return;