X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmetadata%2Fmono-perfcounters.c;h=0fe450027fd0a023516fa6d0f34669d8ac78317e;hb=e0e4793cf9f5c3a62295173735707b240725830e;hp=cd680d3987f368c9a05c07a2c9f19ef7a7b8040e;hpb=dcba1a2bbbb977e5bd670957f4445b00bb73b264;p=mono.git diff --git a/mono/metadata/mono-perfcounters.c b/mono/metadata/mono-perfcounters.c index cd680d3987f..0fe450027fd 100644 --- a/mono/metadata/mono-perfcounters.c +++ b/mono/metadata/mono-perfcounters.c @@ -21,6 +21,7 @@ #include "metadata/class-internals.h" #include "utils/mono-time.h" #include "utils/mono-mmap.h" +#include "utils/mono-proclib.h" #include /* map of CounterSample.cs */ @@ -101,7 +102,7 @@ enum { }; #define PERFCTR_CAT(id,name,help,type,inst,first_counter) CATEGORY_ ## id, -#define PERFCTR_COUNTER(id,name,help,type) +#define PERFCTR_COUNTER(id,name,help,type,field) enum { #include "mono-perfcounters-def.h" NUM_CATEGORIES @@ -110,7 +111,7 @@ enum { #undef PERFCTR_CAT #undef PERFCTR_COUNTER #define PERFCTR_CAT(id,name,help,type,inst,first_counter) CATEGORY_START_ ## id = -1, -#define PERFCTR_COUNTER(id,name,help,type) COUNTER_ ## id, +#define PERFCTR_COUNTER(id,name,help,type,field) COUNTER_ ## id, /* each counter is assigned an id starting from 0 inside the category */ enum { #include "mono-perfcounters-def.h" @@ -120,7 +121,7 @@ enum { #undef PERFCTR_CAT #undef PERFCTR_COUNTER #define PERFCTR_CAT(id,name,help,type,inst,first_counter) -#define PERFCTR_COUNTER(id,name,help,type) CCOUNTER_ ## id, +#define PERFCTR_COUNTER(id,name,help,type,field) CCOUNTER_ ## id, /* this is used just to count the number of counters */ enum { #include "mono-perfcounters-def.h" @@ -231,14 +232,15 @@ typedef struct { typedef struct { const char *name; const char *help; - int id; + short id; + unsigned short offset; // offset inside MonoPerfCounters int type; } CounterDesc; #undef PERFCTR_CAT #undef PERFCTR_COUNTER #define PERFCTR_CAT(id,name,help,type,inst,first_counter) {name, help, CATEGORY_ ## id, type, inst ## Instance, CCOUNTER_ ## first_counter}, -#define PERFCTR_COUNTER(id,name,help,type) +#define PERFCTR_COUNTER(id,name,help,type,field) static const CategoryDesc predef_categories [] = { #include "mono-perfcounters-def.h" @@ -248,11 +250,11 @@ predef_categories [] = { #undef PERFCTR_CAT #undef PERFCTR_COUNTER #define PERFCTR_CAT(id,name,help,type,inst,first_counter) -#define PERFCTR_COUNTER(id,name,help,type) {name, help, COUNTER_ ## id, type}, +#define PERFCTR_COUNTER(id,name,help,type,field) {name, help, COUNTER_ ## id, G_STRUCT_OFFSET (MonoPerfCounters, field), type}, static const CounterDesc predef_counters [] = { #include "mono-perfcounters-def.h" - {NULL, NULL, -1, 0} + {NULL, NULL, -1, 0, 0} }; /* @@ -561,50 +563,10 @@ id_from_string (MonoString *instance, gboolean is_process) return id; } -static void -get_cpu_times (int cpu_id, gint64 *user, gint64 *systemt, gint64 *irq, gint64 *sirq, gint64 *idle) -{ - SYSTEM_INFO info; - char buf [256]; - char *s; - int hz = 100; - long long unsigned int user_ticks, nice_ticks, system_ticks, idle_ticks, iowait_ticks, irq_ticks, sirq_ticks; - FILE *f = fopen ("/proc/stat", "r"); - if (!f) - return; - GetSystemInfo (&info); - hz *= info.dwNumberOfProcessors; - while ((s = fgets (buf, sizeof (buf), f))) { - char *data = NULL; - if (cpu_id < 0 && strncmp (s, "cpu", 3) == 0 && g_ascii_isspace (s [3])) { - data = s + 4; - } else if (cpu_id >= 0 && strncmp (s, "cpu", 3) == 0 && strtol (s + 3, &data, 10) == cpu_id) { - if (data == s + 3) - continue; - data++; - } else { - continue; - } - sscanf (data, "%Lu %Lu %Lu %Lu %Lu %Lu %Lu", &user_ticks, &nice_ticks, &system_ticks, &idle_ticks, &iowait_ticks, &irq_ticks, &sirq_ticks); - } - fclose (f); - - if (user) - *user = (user_ticks + nice_ticks) * 10000000 / hz; - if (systemt) - *systemt = (system_ticks) * 10000000 / hz; - if (irq) - *irq = (irq_ticks) * 10000000 / hz; - if (sirq) - *sirq = (sirq_ticks) * 10000000 / hz; - if (idle) - *idle = (idle_ticks) * 10000000 / hz; -} - static MonoBoolean get_cpu_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample) { - gint64 value = 0; + MonoProcessError error; int id = GPOINTER_TO_INT (vtable->arg); int pid = id >> 5; id &= 0x1f; @@ -615,24 +577,19 @@ get_cpu_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample * sample->counterType = predef_counters [predef_categories [CATEGORY_CPU].first_counter + id].type; switch (id) { case COUNTER_CPU_USER_TIME: - get_cpu_times (pid, &value, NULL, NULL, NULL, NULL); - sample->rawValue = value; + sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_USER_TIME, &error); return TRUE; case COUNTER_CPU_PRIV_TIME: - get_cpu_times (pid, NULL, &value, NULL, NULL, NULL); - sample->rawValue = value; + sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_PRIV_TIME, &error); return TRUE; case COUNTER_CPU_INTR_TIME: - get_cpu_times (pid, NULL, NULL, &value, NULL, NULL); - sample->rawValue = value; + sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_INTR_TIME, &error); return TRUE; case COUNTER_CPU_DCP_TIME: - get_cpu_times (pid, NULL, NULL, NULL, &value, NULL); - sample->rawValue = value; + sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_DCP_TIME, &error); return TRUE; case COUNTER_CPU_PROC_TIME: - get_cpu_times (pid, NULL, NULL, NULL, NULL, &value); - sample->rawValue = value; + sample->rawValue = mono_cpu_get_data (pid, MONO_CPU_IDLE_TIME, &error); return TRUE; } return FALSE; @@ -653,89 +610,6 @@ cpu_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoolean return NULL; } -/* - * /proc/pid/stat format: - * pid (cmdname) S - * [0] ppid pgid sid tty_nr tty_pgrp flags min_flt cmin_flt maj_flt cmaj_flt - * [10] utime stime cutime cstime prio nice threads start_time vsize rss - * [20] rsslim start_code end_code start_stack esp eip pending blocked sigign sigcatch - * [30] wchan 0 0 exit_signal cpu rt_prio policy - */ - -static gint64 -get_process_time (int pid, int pos, int sum) -{ - char buf [512]; - char *s, *end; - FILE *f; - int len, i; - gint64 value; - - g_snprintf (buf, sizeof (buf), "/proc/%d/stat", pid); - f = fopen (buf, "r"); - if (!f) - return 0; - len = fread (buf, 1, sizeof (buf), f); - fclose (f); - if (len <= 0) - return 0; - s = strchr (buf, ')'); - if (!s) - return 0; - s++; - while (g_ascii_isspace (*s)) s++; - if (!*s) - return 0; - /* skip the status char */ - while (*s && !g_ascii_isspace (*s)) s++; - if (!*s) - return 0; - for (i = 0; i < pos; ++i) { - while (g_ascii_isspace (*s)) s++; - if (!*s) - return 0; - while (*s && !g_ascii_isspace (*s)) s++; - if (!*s) - return 0; - } - /* we are finally at the needed item */ - value = strtoul (s, &end, 0); - /* add also the following value */ - if (sum) { - while (g_ascii_isspace (*s)) s++; - if (!*s) - return 0; - value += strtoul (s, &end, 0); - } - return value; -} - -static gint64 -get_pid_stat_item (int pid, const char *item) -{ - char buf [256]; - char *s; - FILE *f; - int len = strlen (item); - - g_snprintf (buf, sizeof (buf), "/proc/%d/status", pid); - f = fopen (buf, "r"); - if (!f) - return 0; - while ((s = fgets (buf, sizeof (buf), f))) { - if (*item != *buf) - continue; - if (strncmp (buf, item, len)) - continue; - if (buf [len] != ':') - continue; - fclose (f); - return atoi (buf + len + 1); - } - fclose (f); - return 0; -} - static MonoBoolean get_process_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample) { @@ -751,25 +625,25 @@ get_process_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSamp sample->counterType = predef_counters [predef_categories [CATEGORY_PROC].first_counter + id].type; switch (id) { case COUNTER_PROC_USER_TIME: - sample->rawValue = get_process_time (pid, 12, FALSE); + sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_USER_TIME); return TRUE; case COUNTER_PROC_PRIV_TIME: - sample->rawValue = get_process_time (pid, 13, FALSE); + sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_SYSTEM_TIME); return TRUE; case COUNTER_PROC_PROC_TIME: - sample->rawValue = get_process_time (pid, 12, TRUE); + sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_TOTAL_TIME); return TRUE; case COUNTER_PROC_THREADS: - sample->rawValue = get_pid_stat_item (pid, "Threads"); + sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_NUM_THREADS); return TRUE; case COUNTER_PROC_VBYTES: - sample->rawValue = get_pid_stat_item (pid, "VmSize") * 1024; + sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_VIRTUAL_BYTES); return TRUE; case COUNTER_PROC_WSET: - sample->rawValue = get_pid_stat_item (pid, "VmRSS") * 1024; + sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_WORKING_SET); return TRUE; case COUNTER_PROC_PBYTES: - sample->rawValue = get_pid_stat_item (pid, "VmData") * 1024; + sample->rawValue = mono_process_get_data (GINT_TO_POINTER (pid), MONO_PROCESS_PRIVATE_BYTES); return TRUE; } return FALSE; @@ -814,7 +688,7 @@ mono_mem_get_impl (MonoString* counter, MonoString* instance, int *type, MonoBoo *custom = FALSE; if ((cdesc = get_counter_in_category (&predef_categories [CATEGORY_MONO_MEM], counter))) { *type = cdesc->type; - return create_vtable (GINT_TO_POINTER (cdesc->id), mono_mem_counter, NULL); + return create_vtable (GINT_TO_POINTER ((gint) cdesc->id), mono_mem_counter, NULL); } return NULL; } @@ -823,6 +697,7 @@ static MonoBoolean predef_readonly_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounterSample *sample) { PredefVtable *vt = (PredefVtable *)vtable; + const CounterDesc *desc; int cat_id = GPOINTER_TO_INT (vtable->arg); int id = cat_id >> 16; cat_id &= 0xffff; @@ -830,36 +705,12 @@ predef_readonly_counter (ImplVtable *vtable, MonoBoolean only_value, MonoCounter fill_sample (sample); sample->baseValue = 1; } - sample->counterType = predef_counters [predef_categories [cat_id].first_counter + id].type; - switch (cat_id) { - case CATEGORY_JIT: - switch (id) { - case COUNTER_JIT_BYTES: - case COUNTER_JIT_BYTES_PSEC: - sample->rawValue = vt->counters->jit_bytes; - return TRUE; - case COUNTER_JIT_METHODS: - sample->rawValue = vt->counters->jit_methods; - return TRUE; - } - break; - case CATEGORY_EXC: - switch (id) { - case COUNTER_EXC_THROWN: - case COUNTER_EXC_THROWN_PSEC: - sample->rawValue = vt->counters->exceptions_thrown; - return TRUE; - } - break; - - case CATEGORY_ASPNET: - switch (id) { - case COUNTER_ASPNET_REQ_Q: - sample->rawValue = vt->counters->aspnet_requests_queued; - return TRUE; - } - } - return FALSE; + desc = &predef_counters [predef_categories [cat_id].first_counter + id]; + sample->counterType = desc->type; + /* FIXME: check that the offset fits inside imported counters */ + /*g_print ("loading %s at %d\n", desc->name, desc->offset);*/ + sample->rawValue = *(guint32*)((char*)vt->counters + desc->offset); + return TRUE; } static ImplVtable* @@ -880,7 +731,7 @@ predef_vtable (void *arg, MonoString *instance) vtable->vtable.arg = arg; vtable->vtable.sample = predef_readonly_counter; vtable->vtable.cleanup = predef_cleanup; - vtable->counters = &area->counters; + vtable->counters = (MonoPerfCounters*)((char*)area + area->counters_start); vtable->pid = pid; return (ImplVtable*)vtable; @@ -1035,6 +886,12 @@ mono_perfcounter_get_impl (MonoString* category, MonoString* counter, MonoString return mono_mem_get_impl (counter, instance, type, custom); case CATEGORY_JIT: case CATEGORY_EXC: + case CATEGORY_GC: + case CATEGORY_REMOTING: + case CATEGORY_LOADING: + case CATEGORY_THREAD: + case CATEGORY_INTEROP: + case CATEGORY_SECURITY: case CATEGORY_ASPNET: return predef_writable_get_impl (cdesc->id, counter, instance, type, custom); } @@ -1297,27 +1154,6 @@ mono_perfcounter_counter_names (MonoString *category, MonoString *machine) return mono_array_new (domain, mono_get_string_class (), 0); } -static char* -read_proc_name (int pid, char *buf, int len) -{ - char fname [128]; - FILE *file; - char *p; - int r; - sprintf (fname, "/proc/%d/cmdline", pid); - buf [0] = 0; - file = fopen (fname, "r"); - if (!file) - return buf; - r = fread (buf, 1, len - 1, file); - fclose (file); - buf [r] = 0; - p = strrchr (buf, '/'); - if (p) - return p + 1; - return buf; -} - static MonoArray* get_string_array (void **array, int count, gboolean is_process) { @@ -1328,7 +1164,7 @@ get_string_array (void **array, int count, gboolean is_process) char buf [128]; char *p; if (is_process) { - char *pname = read_proc_name (GPOINTER_TO_INT (array [i]), buf, sizeof (buf)); + char *pname = mono_process_get_name (array [i], buf, sizeof (buf)); p = g_strdup_printf ("%d/%s", GPOINTER_TO_INT (array [i]), pname); } else { sprintf (buf, "%d", GPOINTER_TO_INT (array [i])); @@ -1363,14 +1199,13 @@ static MonoArray* get_cpu_instances (void) { void **buf = NULL; - int i; + int i, count; MonoArray *array; - SYSTEM_INFO info; - GetSystemInfo (&info); - buf = g_new (void*, info.dwNumberOfProcessors); - for (i = 0; i < info.dwNumberOfProcessors; ++i) + count = mono_cpu_count (); + buf = g_new (void*, count); + for (i = 0; i < count; ++i) buf [i] = GINT_TO_POINTER (i); - array = get_string_array (buf, info.dwNumberOfProcessors, FALSE); + array = get_string_array (buf, count, FALSE); g_free (buf); return array; } @@ -1378,31 +1213,12 @@ get_cpu_instances (void) static MonoArray* get_processes_instances (void) { - const char *name; - void **buf = NULL; - int count = 0; - int i = 0; MonoArray *array; - GDir *dir = g_dir_open ("/proc/", 0, NULL); - if (!dir) + int count = 0; + void **buf = mono_process_list (&count); + if (!buf) return get_string_array (NULL, 0, FALSE); - while ((name = g_dir_read_name (dir))) { - int pid; - char *nend; - pid = strtol (name, &nend, 10); - if (pid <= 0 || nend == name || *nend) - continue; - if (i >= count) { - if (!count) - count = 16; - else - count *= 2; - buf = g_realloc (buf, count * sizeof (void*)); - } - buf [i++] = GINT_TO_POINTER (pid); - } - g_dir_close (dir); - array = get_string_array (buf, i, TRUE); + array = get_string_array (buf, count, TRUE); g_free (buf); return array; }