-
-
Save luhenry/9606220 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/mono/mini/driver.c b/mono/mini/driver.c | |
index d71c077..be72e56 100644 | |
--- a/mono/mini/driver.c | |
+++ b/mono/mini/driver.c | |
@@ -47,6 +47,7 @@ | |
#include <mono/metadata/coree.h> | |
#include <mono/metadata/attach.h> | |
#include "mono/utils/mono-counters.h" | |
+#include <mono/utils/mono-counters-internals.h> | |
#include "mono/utils/mono-hwcap.h" | |
#include "mini.h" | |
@@ -1382,9 +1383,7 @@ mono_jit_parse_options (int argc, char * argv[]) | |
opt->break_on_exc = TRUE; | |
} else if (strcmp (argv [i], "--stats") == 0) { | |
- mono_counters_enable (-1); | |
- mono_stats.enabled = TRUE; | |
- mono_jit_stats.enabled = TRUE; | |
+ mono_counters_dump_on_cleanup(); | |
} else if (strcmp (argv [i], "--break") == 0) { | |
if (i+1 >= argc){ | |
fprintf (stderr, "Missing method name in --break command line option\n"); | |
@@ -1406,6 +1405,11 @@ mono_jit_parse_options (int argc, char * argv[]) | |
exit (1); | |
} | |
} | |
+ | |
+ // Always enable mono counters | |
+ mono_counters_enable (-1); | |
+ mono_stats.enabled = TRUE; | |
+ mono_jit_stats.enabled = TRUE; | |
if (trace_options != NULL) { | |
/* | |
@@ -1653,9 +1657,7 @@ mono_main (int argc, char* argv[]) | |
} else if (strcmp (argv [i], "--print-vtable") == 0) { | |
mono_print_vtable = TRUE; | |
} else if (strcmp (argv [i], "--stats") == 0) { | |
- mono_counters_enable (-1); | |
- mono_stats.enabled = TRUE; | |
- mono_jit_stats.enabled = TRUE; | |
+ mono_counters_dump_on_cleanup(); | |
#ifndef DISABLE_AOT | |
} else if (strcmp (argv [i], "--aot") == 0) { | |
error_if_aot_unsupported (); | |
@@ -1824,6 +1826,11 @@ mono_main (int argc, char* argv[]) | |
} | |
} | |
+ // Always enable mono counters | |
+ mono_counters_enable (-1); | |
+ mono_stats.enabled = TRUE; | |
+ mono_jit_stats.enabled = TRUE; | |
+ | |
#ifdef __native_client_codegen__ | |
if (g_getenv ("MONO_NACL_ALIGN_MASK_OFF")) | |
{ | |
diff --git a/mono/mini/mini.c b/mono/mini/mini.c | |
index 616d696..2a0e06c 100644 | |
--- a/mono/mini/mini.c | |
+++ b/mono/mini/mini.c | |
@@ -53,6 +53,7 @@ | |
#include <mono/utils/mono-math.h> | |
#include <mono/utils/mono-compiler.h> | |
#include <mono/utils/mono-counters.h> | |
+#include <mono/utils/mono-counters-internals.h> | |
#include <mono/utils/mono-logger-internal.h> | |
#include <mono/utils/mono-mmap.h> | |
#include <mono/utils/mono-path.h> | |
@@ -7643,7 +7644,7 @@ MonoJitStats mono_jit_stats = {0}; | |
static void | |
print_jit_stats (void) | |
{ | |
- if (mono_jit_stats.enabled) { | |
+ if (mono_jit_stats.enabled && mono_counters_dump_on_cleanup_enable()) { | |
g_print ("Mono Jit statistics\n"); | |
g_print ("Max code size ratio: %.2f (%s)\n", mono_jit_stats.max_code_size_ratio/100.0, | |
mono_jit_stats.max_ratio_method); | |
diff --git a/mono/utils/Makefile.am b/mono/utils/Makefile.am | |
index 1a4f6ac..2e7961c 100644 | |
--- a/mono/utils/Makefile.am | |
+++ b/mono/utils/Makefile.am | |
@@ -21,7 +21,7 @@ monoutils_sources = \ | |
dlmalloc.c \ | |
mono-counters.c \ | |
mono-compiler.h \ | |
- mono-counters-internals.h \ | |
+ mono-compiler-internals.h \ | |
mono-dl.c \ | |
mono-dl.h \ | |
mono-internal-hash.c \ | |
@@ -69,6 +69,7 @@ monoutils_sources = \ | |
monobitset.h \ | |
mono-codeman.h \ | |
mono-counters.h \ | |
+ mono-counters-internals.h \ | |
mono-digest.h \ | |
mono-error.h \ | |
mono-machine.h \ | |
@@ -111,7 +112,9 @@ monoutils_sources = \ | |
mono-hwcap.c \ | |
bsearch.h \ | |
bsearch.c \ | |
- mono-signal-handler.h | |
+ mono-signal-handler.h \ | |
+ mono-counters-agent.c \ | |
+ mono-counters-agent.h | |
arch_sources = | |
diff --git a/mono/utils/mono-counters-agent.c b/mono/utils/mono-counters-agent.c | |
new file mode 100644 | |
index 0000000..2737c17 | |
--- /dev/null | |
+++ b/mono/utils/mono-counters-agent.c | |
@@ -0,0 +1,281 @@ | |
+/* | |
+ * Copyright 2014 Xamarin Inc | |
+ */ | |
+ | |
+#include <stdlib.h> | |
+#include <stdio.h> | |
+#include <errno.h> | |
+#include <pthread.h> | |
+#include <glib.h> | |
+#include <unistd.h> | |
+#include <arpa/inet.h> | |
+#include <netinet/in.h> | |
+#include <netinet/tcp.h> | |
+#include <sys/socket.h> | |
+#include <sys/time.h> | |
+#include <sys/types.h> | |
+#include "mono-counters.h" | |
+#include "mono-counters-internals.h" | |
+#include "mono-counters-agent.h" | |
+#include "mono-time.h" | |
+ | |
+/** | |
+ * Protocol : | |
+ * | Headers | Values | Values | ... [Infinity] | |
+ * | |
+ * Headers : | |
+ * | Count (2) | Counter | Counter | ... [Count] | |
+ * | |
+ * Counter : | |
+ * | Category (4) | Name Length (8) | Name (Name Length) | Type (4) | Unit (4) | Variance (4) | Index (2) | | |
+ * | |
+ * Values : | |
+ * | Timestamp (8) | Value | Value | ... | -1 (2) | | |
+ * | |
+ * Value : | |
+ * | Index (2) | Size (2) | Value (Size) | | |
+ */ | |
+ | |
+typedef struct MonoCounterAgent { | |
+ MonoCounter* counter; | |
+ // MonoCounterAgent specific data : | |
+ void* value; | |
+ short index; | |
+} MonoCounterAgent; | |
+ | |
+static pthread_t agent_thread; | |
+ | |
+static GSList* counters; | |
+ | |
+static const gchar* inspector_ip; | |
+static int inspector_port; | |
+static int frequency; | |
+ | |
+static int enable; | |
+ | |
+int | |
+parse_counters_all (MonoCounter* counter, void** args) | |
+{ | |
+ static short index = 0; | |
+ | |
+ MonoCounterAgent* _counter = g_malloc(sizeof(MonoCounterAgent)); | |
+ _counter->counter = counter; | |
+ _counter->value = NULL; | |
+ _counter->index = index; | |
+ | |
+ counters = g_slist_append (counters, _counter); | |
+ index += 1; | |
+ | |
+ return 1; | |
+} | |
+ | |
+void | |
+parse_counters_names (const char *counters_names) | |
+{ | |
+ if (!counters_names) { | |
+ mono_counters_foreach(parse_counters_all, NULL); | |
+ } else { | |
+ short index = 0; | |
+ gchar **names = g_strsplit (counters_names, ";", -1), **ptr; | |
+ | |
+ for (ptr = names; *ptr; ++ptr) { | |
+ gchar **split = g_strsplit(*ptr, "/", 2); | |
+ if (!split[0] || !split[1]) | |
+ continue; //FIXME warning | |
+ | |
+ MonoCounterCategory category = mono_counters_category_name_to_id (split[0]); | |
+ MonoCounter* counter = mono_counters_get (category, split[1]); | |
+ if (!counter) | |
+ continue; // FIXME warning= | |
+ | |
+ MonoCounterAgent* _counter = g_malloc(sizeof(MonoCounterAgent)); | |
+ _counter->counter = counter; | |
+ _counter->index = index; | |
+ _counter->value = NULL; | |
+ | |
+ counters = g_slist_append (counters, _counter); | |
+ index += 1; | |
+ | |
+ g_strfreev(split); | |
+ } | |
+ g_strfreev (names); | |
+ } | |
+} | |
+ | |
+void | |
+parse_address (const char *address) | |
+{ | |
+ if (!address) { | |
+ inspector_ip = "127.0.0.1"; | |
+ inspector_port = 8888; | |
+ } else { | |
+ gchar **split = g_strsplit(address, ":", 2); | |
+ | |
+ inspector_ip = (split[0]) ? g_strdup(split[0]) : "127.0.0.1"; | |
+ inspector_port = (split[1]) ? strtol(split[1], NULL, 10) : 8888; | |
+ | |
+ g_strfreev(split); | |
+ } | |
+} | |
+ | |
+int | |
+write_buffer_to_socket(int socketfd, char* buffer, ssize_t size) | |
+{ | |
+ ssize_t left = size, sent; | |
+ | |
+ while (left > 0) { | |
+ sent = send(socketfd, buffer + (size - left), left, 0); | |
+ if (sent <= 0) | |
+ return 0; | |
+ left -= sent; | |
+ } | |
+ | |
+ return 1; | |
+} | |
+ | |
+static void* | |
+mono_counters_agent_sampling_thread (void* ptr) | |
+{ | |
+ int socketfd = 0; | |
+ struct sockaddr_in inspector_addr; | |
+ | |
+ if ((socketfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | |
+ g_printf("mono-counters-agent | error with socket : %s", strerror(errno)); | |
+ return NULL; | |
+ } | |
+ | |
+ memset(&inspector_addr, 0, sizeof(inspector_addr)); | |
+ | |
+ inspector_addr.sin_family = AF_INET; | |
+ inspector_addr.sin_port = htons(inspector_port); | |
+ | |
+ if (!inet_pton(AF_INET, inspector_ip, &inspector_addr.sin_addr)) { | |
+ g_printf("mono-counters-agent | error with inet_pton : %s", strerror(errno)); | |
+ return NULL; | |
+ } | |
+ | |
+ if (connect(socketfd, (struct sockaddr*)&inspector_addr, sizeof(inspector_addr)) < 0) { | |
+ g_printf("mono-counters-agent | error with connect : %s", strerror(errno)); | |
+ return NULL; | |
+ } | |
+ | |
+ GSList* item; | |
+ char* buffer = g_malloc(8); | |
+ | |
+ short count = 0; | |
+ for (item = counters; item; item = item->next) | |
+ count += 1; | |
+ | |
+ if (!write_buffer_to_socket(socketfd, (char*)&count, 2)) | |
+ goto cleanup; | |
+ | |
+ for (item = counters; item; item = item->next) { | |
+ MonoCounterAgent* counter = item->data; | |
+ | |
+ int len = strlen(counter->counter->name); | |
+ | |
+ if (!write_buffer_to_socket(socketfd, (char*)&counter->counter->category, 4) | |
+ || !write_buffer_to_socket(socketfd, (char*)&len, 4) | |
+ || !write_buffer_to_socket(socketfd, (char*) counter->counter->name, len) | |
+ || !write_buffer_to_socket(socketfd, (char*)&counter->counter->type, 4) | |
+ || !write_buffer_to_socket(socketfd, (char*)&counter->counter->unit, 4) | |
+ || !write_buffer_to_socket(socketfd, (char*)&counter->counter->variance, 4) | |
+ || !write_buffer_to_socket(socketfd, (char*)&counter->index, 2)) | |
+ goto cleanup; // FIXME error | |
+ } | |
+ | |
+ while (enable) { | |
+ gint64 timestamp = mono_100ns_ticks(); | |
+ if (!write_buffer_to_socket(socketfd, (char*)×tamp, 8)) | |
+ goto cleanup; // FIXME error | |
+ | |
+ for (item = counters; item; item = item->next) { | |
+ MonoCounterAgent* counter = item->data; | |
+ | |
+ if (!counter) | |
+ continue; // FIXME warning | |
+ | |
+ int size = mono_counters_size(counter->counter); | |
+ | |
+ if (mono_counters_sample (counter->counter, buffer, size) != size) | |
+ goto cleanup; | |
+ | |
+ if (!counter->value) | |
+ counter->value = g_malloc(size); | |
+ else if (memcmp(counter->value, buffer, size) == 0) | |
+ continue; | |
+ | |
+ memcpy(counter->value, buffer, size); | |
+ | |
+ if (!write_buffer_to_socket(socketfd, (char*)&counter->index, 2) | |
+ || !write_buffer_to_socket(socketfd, (char*)&size, 2) | |
+ || !write_buffer_to_socket(socketfd, (char*) buffer, size)) | |
+ goto cleanup; | |
+ } | |
+ | |
+ short end = -1; | |
+ if (!write_buffer_to_socket(socketfd, (char*)&end, 2)) | |
+ goto cleanup; // FIXME error | |
+ | |
+ usleep (1000000 / frequency); | |
+ } | |
+ | |
+cleanup: | |
+ close(socketfd); | |
+ g_free(buffer); | |
+ | |
+ return NULL; | |
+} | |
+ | |
+void | |
+parse_configuration (const gchar* configuration) | |
+{ | |
+ const char *counters_names = NULL; | |
+ const char *address = NULL; | |
+ | |
+ if (configuration == NULL) | |
+ return; | |
+ | |
+ gchar **opts = g_strsplit (configuration, ",", -1), **ptr; | |
+ for (ptr = opts; *ptr; ++ptr) { | |
+ const char *opt = *ptr; | |
+ if (g_str_has_prefix (opt, "address=")) { | |
+ opt = strchr (opt, '=') + 1; | |
+ address = g_strdup(opt); | |
+ } else if (g_str_has_prefix (opt, "counters=")) { | |
+ opt = strchr (opt, '=') + 1; | |
+ counters_names = g_strdup(opt); | |
+ } else if (g_str_has_prefix (opt, "frequency=")) { | |
+ opt = strchr (opt, '=') + 1; | |
+ frequency = strtol (opt, NULL, 10); | |
+ } | |
+ } | |
+ | |
+ parse_counters_names(counters_names); | |
+ parse_address(address); | |
+ | |
+ g_free((void*)counters_names); | |
+ g_free((void*)address); | |
+ g_strfreev(opts); | |
+} | |
+ | |
+void | |
+mono_counters_agent_start (void) | |
+{ | |
+ enable = 1; | |
+ | |
+ // counters = g_slist_alloc(); | |
+ | |
+ parse_configuration(g_getenv ("MONO_PERF_AGENT")); | |
+ pthread_create(&agent_thread, NULL, mono_counters_agent_sampling_thread, NULL); | |
+} | |
+ | |
+void | |
+mono_counters_agent_stop(void) | |
+{ | |
+ enable = 0; | |
+ | |
+ g_slist_free(counters); | |
+ | |
+ pthread_join(agent_thread, NULL); | |
+} | |
\ No newline at end of file | |
diff --git a/mono/utils/mono-counters-agent.h b/mono/utils/mono-counters-agent.h | |
new file mode 100644 | |
index 0000000..c7e275a | |
--- /dev/null | |
+++ b/mono/utils/mono-counters-agent.h | |
@@ -0,0 +1,7 @@ | |
+#ifndef __MONO_COUNTERS_AGENTS_H__ | |
+#define __MONO_COUNTERS_AGENTS_H__ | |
+ | |
+MONO_API void mono_counters_agent_start (void); | |
+MONO_API void mono_counters_agent_stop (void); | |
+ | |
+#endif /* __MONO_COUNTERS_AGENTS_H__ */ | |
\ No newline at end of file | |
diff --git a/mono/utils/mono-counters-internals.h b/mono/utils/mono-counters-internals.h | |
index a8cbfef..22304bf 100644 | |
--- a/mono/utils/mono-counters-internals.h | |
+++ b/mono/utils/mono-counters-internals.h | |
@@ -1,6 +1,7 @@ | |
#ifndef __MONO_COUNTERS_INTERNALS_H__ | |
#define __MONO_COUNTERS_INTERNALS_H__ | |
+#include <glib.h> | |
#include "mono-counters.h" | |
#include "mono-compiler.h" | |
@@ -41,7 +42,16 @@ typedef enum { | |
MONO_COUNTER_UNIT_VARIABLE, /* This counter value can be anything on each sampling */ | |
} MonoCounterVariance; | |
-typedef struct _MonoCounter MonoCounter; | |
+typedef struct _MonoCounter { | |
+ const char* name; | |
+ void* addr; | |
+ MonoCounterType type; | |
+ MonoCounterCategory category; | |
+ MonoCounterUnit unit; | |
+ MonoCounterVariance variance; | |
+ gboolean is_callback; | |
+} MonoCounter; | |
+ | |
/* | |
Limitations: | |
The old-style string counter type won't work as they cannot be safely sampled during execution. | |
@@ -68,5 +78,19 @@ mono_counters_register_full (MonoCounterCategory category, const char *name, Mon | |
#define mono_counters_new_long_const(cat,name,unit,value) do { gint64 *__ptr = mono_counters_new(cat,name,MONO_COUNTER_TYPE_INT,unit,variance); *__ptr = value; } while (0) | |
#define mono_counters_new_double_const(cat,name,unit,value) do { double *__ptr = mono_counters_new(cat,name,MONO_COUNTER_TYPE_INT,unit,variance); *__ptr = value; } while (0) | |
+MONO_API void mono_counters_dump_on_cleanup (void); | |
+MONO_API int mono_counters_dump_on_cleanup_enable (void); | |
+ | |
+MONO_API MonoCounter* mono_counters_get (MonoCounterCategory category, const char* name); | |
+MONO_API int mono_counters_sample (MonoCounter* counter, char* buffer, int size); | |
+MONO_API int mono_counters_size (MonoCounter* counter); | |
+ | |
+MONO_API MonoCounterCategory mono_counters_category_name_to_id (const char* name); | |
+MONO_API const char* mono_counters_category_id_to_name (MonoCounterCategory id); | |
+ | |
+typedef int (*MonoCountersForeachFunc) (MonoCounter* counter, void** args); | |
+MONO_API void mono_counters_foreach(MonoCountersForeachFunc func, void** args); | |
+ | |
+ | |
+#endif /* __MONO_COUNTERS_INTERNALS_H__ */ | |
-#endif | |
diff --git a/mono/utils/mono-counters.c b/mono/utils/mono-counters.c | |
index 9f22e01..430500b 100644 | |
--- a/mono/utils/mono-counters.c | |
+++ b/mono/utils/mono-counters.c | |
@@ -5,22 +5,14 @@ | |
#include <stdlib.h> | |
#include <glib.h> | |
+#include "mono-counters.h" | |
#include "mono-counters-internals.h" | |
-struct _MonoCounter { | |
- MonoCounter *next; | |
- const char *name; | |
- void *addr; | |
- MonoCounterType type; | |
- MonoCounterCategory category; | |
- MonoCounterUnit unit; | |
- MonoCounterVariance variance; | |
- gboolean is_callback; | |
-}; | |
- | |
-static MonoCounter *counters = NULL; | |
+static GSList *counters = NULL; | |
static int valid_mask = 0; | |
+static int dump_on_cleanup = 0; | |
+ | |
/** | |
* mono_counters_enable: | |
* @section_mask: a mask listing the sections that will be displayed | |
@@ -46,17 +38,9 @@ mono_counters_register_full (MonoCounterCategory category, const char *name, Mon | |
counter->category = category; | |
counter->unit = unit; | |
counter->variance = variance; | |
- counter->next = NULL; | |
- | |
- /* Append */ | |
- if (counters) { | |
- MonoCounter *item = counters; | |
- while (item->next) | |
- item = item->next; | |
- item->next = counter; | |
- } else { | |
- counters = counter; | |
- } | |
+ | |
+ counters = g_slist_append (counters, counter); | |
+ | |
return counter; | |
} | |
@@ -104,6 +88,18 @@ section_to_category (int type) | |
} | |
} | |
+void | |
+mono_counters_dump_on_cleanup (void) | |
+{ | |
+ dump_on_cleanup = 1; | |
+} | |
+ | |
+int | |
+mono_counters_dump_on_cleanup_enable (void) | |
+{ | |
+ return dump_on_cleanup; | |
+} | |
+ | |
/** | |
* mono_counters_register: | |
* @name: The name for this counters. | |
@@ -153,6 +149,8 @@ mono_counters_register (const char* name, int type, void *addr) | |
counter = mono_counters_register_full (cat, name, counter_type, unit, MONO_COUNTER_UNIT_VARIABLE, addr); | |
if (counter && type & MONO_COUNTER_CALLBACK) | |
counter->is_callback = TRUE; | |
+ else | |
+ counter->is_callback = FALSE; | |
} | |
@@ -220,11 +218,12 @@ section_names [][10] = { | |
static void | |
mono_counters_dump_category (MonoCounterCategory category, FILE *outfile) | |
{ | |
- MonoCounter *counter = counters; | |
- while (counter) { | |
+ GSList *item = counters; | |
+ while (item) { | |
+ MonoCounter* counter = item->data; | |
if (counter->category == category) | |
dump_counter (counter, outfile); | |
- counter = counter->next; | |
+ item = item->next; | |
} | |
} | |
@@ -238,6 +237,9 @@ mono_counters_dump_category (MonoCounterCategory category, FILE *outfile) | |
void | |
mono_counters_dump (int section_mask, FILE *outfile) | |
{ | |
+ if (!dump_on_cleanup) | |
+ return; | |
+ | |
int i, j; | |
section_mask &= valid_mask; | |
if (!counters) | |
@@ -260,13 +262,8 @@ mono_counters_dump (int section_mask, FILE *outfile) | |
void | |
mono_counters_cleanup (void) | |
{ | |
- MonoCounter *counter = counters; | |
- counters = NULL; | |
- while (counter) { | |
- MonoCounter *tmp = counter; | |
- counter = counter->next; | |
- free (tmp); | |
- } | |
+ if (counters) | |
+ g_slist_free(counters); | |
} | |
static MonoResourceCallback limit_reached = NULL; | |
@@ -334,4 +331,156 @@ mono_runtime_resource_set_callback (MonoResourceCallback callback) | |
limit_reached = callback; | |
} | |
+MonoCounter* | |
+mono_counters_get (MonoCounterCategory category, const char* name) | |
+{ | |
+ if (!counters) | |
+ return NULL; | |
+ | |
+ GSList* item = counters; | |
+ | |
+ do { | |
+ MonoCounter* counter = item->data; | |
+ if (counter->category == category && strcmp(counter->name, name) ==0) | |
+ return counter; | |
+ } while ((item = item->next)); | |
+} | |
+ | |
+int | |
+mono_counters_sample (MonoCounter* counter, char* buffer, int size) | |
+{ | |
+ switch (counter->type) { | |
+ case MONO_COUNTER_TYPE_INT: | |
+#if SIZEOF_VOID_P == 4 | |
+ case MONO_COUNTER_TYPE_WORD: | |
+#endif | |
+ if (size < 4) | |
+ return -1; | |
+ | |
+ if (counter->is_callback) { | |
+ int value = ((IntFunc)counter->addr) (); | |
+ memcpy(buffer, &value, 4); | |
+ } else { | |
+ memcpy(buffer, counter->addr, 4); | |
+ } | |
+ | |
+ return 4; | |
+ case MONO_COUNTER_TYPE_LONG: | |
+#if SIZEOF_VOID_P == 8 | |
+ case MONO_COUNTER_TYPE_WORD: | |
+#endif | |
+ if (size < 8) | |
+ return -1; | |
+ | |
+ if (counter->is_callback) { | |
+ long value = ((LongFunc)counter->addr) (); | |
+ memcpy(buffer, &value, 8); | |
+ } else { | |
+ memcpy(buffer, counter->addr, 8); | |
+ } | |
+ | |
+ return 8; | |
+ case MONO_COUNTER_DOUBLE: | |
+ if (size < 8) | |
+ return -1; | |
+ | |
+ if (counter->is_callback) { | |
+ double value = ((DoubleFunc)counter->addr) (); | |
+ memcpy(buffer, &value, 8); | |
+ } else { | |
+ memcpy(buffer, counter->addr, 8); | |
+ } | |
+ | |
+ return 8; | |
+ } | |
+} | |
+ | |
+int | |
+mono_counters_size (MonoCounter* counter) | |
+{ | |
+ switch (counter->type) { | |
+ case MONO_COUNTER_TYPE_INT: | |
+#if SIZEOF_VOID_P == 4 | |
+ case MONO_COUNTER_TYPE_WORD: | |
+#endif | |
+ return 4; | |
+ case MONO_COUNTER_TYPE_LONG: | |
+#if SIZEOF_VOID_P == 8 | |
+ case MONO_COUNTER_TYPE_WORD: | |
+#endif | |
+ case MONO_COUNTER_DOUBLE: | |
+ return 8; | |
+ } | |
+} | |
+ | |
+MonoCounterCategory | |
+mono_counters_category_name_to_id (const char* name) | |
+{ | |
+ if (strcmp("Mono JIT", name) == 0) { | |
+ return MONO_COUNTER_CAT_JIT; | |
+ } else if (strcmp("Mono GC", name) == 0) { | |
+ return MONO_COUNTER_CAT_GC; | |
+ } else if (strcmp("Mono Metadata", name) == 0) { | |
+ return MONO_COUNTER_CAT_METADATA; | |
+ } else if (strcmp("Mono Generics", name) == 0) { | |
+ return MONO_COUNTER_CAT_GENERICS; | |
+ } else if (strcmp("Mono Security", name) == 0) { | |
+ return MONO_COUNTER_CAT_SECURITY; | |
+ } else if (strcmp("Mono Remoting", name) == 0) { | |
+ return MONO_COUNTER_CAT_REMOTING; | |
+ } else if (strcmp("Mono EXC", name) == 0) { | |
+ return MONO_COUNTER_CAT_EXC; | |
+ } else if (strcmp("Mono Thread", name) == 0) { | |
+ return MONO_COUNTER_CAT_THREAD; | |
+ } else if (strcmp("Mono Threadpool", name) == 0) { | |
+ return MONO_COUNTER_CAT_THREADPOOL; | |
+ } else if (strcmp("Mono IO", name) == 0) { | |
+ return MONO_COUNTER_CAT_IO; | |
+ } else { | |
+ return -1; | |
+ } | |
+} | |
+ | |
+const char* | |
+mono_counters_category_id_to_name (MonoCounterCategory id) | |
+{ | |
+ switch (id) { | |
+ case MONO_COUNTER_CAT_JIT: | |
+ return "Mono JIT"; | |
+ case MONO_COUNTER_CAT_GC: | |
+ return "Mono GC"; | |
+ case MONO_COUNTER_CAT_METADATA: | |
+ return "Mono Metadata"; | |
+ case MONO_COUNTER_CAT_GENERICS: | |
+ return "Mono Generics"; | |
+ case MONO_COUNTER_CAT_SECURITY: | |
+ return "Mono Security"; | |
+ case MONO_COUNTER_CAT_REMOTING: | |
+ return "Mono Remoting"; | |
+ case MONO_COUNTER_CAT_EXC: | |
+ return "Mono EXC"; | |
+ case MONO_COUNTER_CAT_THREAD: | |
+ return "Mono Thread"; | |
+ case MONO_COUNTER_CAT_THREADPOOL: | |
+ return "Mono Threadpool"; | |
+ case MONO_COUNTER_CAT_IO: | |
+ return "Mono IO"; | |
+ default: | |
+ return NULL; | |
+ } | |
+} | |
+ | |
+void | |
+mono_counters_foreach(MonoCountersForeachFunc func, void** args) | |
+{ | |
+ if (!counters) | |
+ return; | |
+ | |
+ GSList* item = counters; | |
+ | |
+ do { | |
+ if (!func(item->data, args)) | |
+ return; | |
+ } while ((item = item->next)); | |
+} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment