Hello,

A pair of years ago I wrote a small patch for saving the profile output
to a xml file. It's almost sure that you won't be able to apply this
patch to the current sources, but it could help you to write a custom
profiler or just 'catch' the info.

Carlos.

El vie, 24-03-2006 a las 07:44 +0100, Jacob Ilsø Christensen escribió:
> Hi.
> 
> On 3/23/06, Robert Jordan <[EMAIL PROTECTED]> wrote:
> > Hey,
> >
> > Jacob Ilsø Christensen wrote:
> > > Hi.
> > >
> > > I have been experimenting a bit with monos profiling option. I run
> > > mono like this:
> > >
> > > mono --profile=default:time A.exe
> > >
> > > This results in the profiling information being printed to stdout. Is
> > > there a way to redirect this information to e.g. a file to prevent it
> > > from being mixed with the output from the program (A.exe) itself?
> >
> > It depends on your shell. With sh/bash you can redirect both
> > output streams to different files:
> >
> > mono --profile=default:time A.exe  2> errors  1> output
> 
> That's not exactly what I meant. What I want is a way to prevent the
> output from the profiler from being mingled with the output from the
> application being profiled.
> 
> Any ideas?
> 
> /Jacob
> 
> >
> > Robert
> >
> > _______________________________________________
> > Mono-devel-list mailing list
> > Mono-devel-list@lists.ximian.com
> > http://lists.ximian.com/mailman/listinfo/mono-devel-list
> >
> _______________________________________________
> Mono-devel-list mailing list
> Mono-devel-list@lists.ximian.com
> http://lists.ximian.com/mailman/listinfo/mono-devel-list
? xml_profile.diff
Index: profiler.c
===================================================================
RCS file: /cvs/public/mono/mono/metadata/profiler.c,v
retrieving revision 1.20
diff -u -r1.20 profiler.c
--- profiler.c	22 Mar 2004 17:48:46 -0000	1.20
+++ profiler.c	24 Mar 2004 02:45:20 -0000
@@ -7,6 +7,8 @@
 #include <gmodule.h>
 
 static MonoProfiler * current_profiler = NULL;
+static const char *profiler_xml_file = NULL;
+static FILE *xml_file = NULL;
 
 static MonoProfileAppDomainFunc   domain_start_load;
 static MonoProfileAppDomainResult domain_end_load;
@@ -682,6 +684,61 @@
 	printf ("Total number of calls: %lld\n", total_calls);
 }
 
+static guint64
+total_number_calls (GList *funcs)
+{
+	GList *tmp;
+	MethodProfile *mp;
+	guint64 total_calls = 0;
+
+	for (tmp = funcs; tmp; tmp = tmp->next) {
+		mp = tmp->data;
+		total_calls += mp->count;
+	}
+
+	return total_calls;
+}
+
+static gboolean output_callers_xml (MethodProfile *p);
+
+static gboolean
+output_profile_xml (GList *funcs)
+{
+	char *m;
+	GList *tmp;
+	guint64 total_calls;
+	int length;
+	MethodProfile *p;
+
+	total_calls = total_number_calls (funcs);
+	length = fprintf (xml_file, "\t<time calls=\"%lld\">\n", total_calls);
+	if (length < 0)
+		return FALSE;
+
+	for (tmp = funcs; tmp; tmp = tmp->next) {
+		p = tmp->data;
+
+		if (!(gint)(p->total*1000))
+			continue;
+
+		m = method_get_name (p->method);
+		length = fprintf (xml_file, "\t\t<method count=\"%llu\" name=\"%s\" time=\"%f\" total=\"%f\">\n",
+				p->count, m, (double) (p->total * 1000)/(double) p->count, (double) p->total * 1000);
+		
+		if (length < 0 || !output_callers_xml (p))
+			return FALSE;
+
+		length = fprintf (xml_file, "\t\t</method>\n");
+		g_free (m);
+
+		if (length < 0)
+			return FALSE;
+	}
+	length = fprintf (xml_file, "\t</time>\n");
+	
+	return (length > 0)?TRUE:FALSE;
+}
+
 typedef struct {
 	MethodProfile *mp;
 	guint count;
@@ -766,6 +823,106 @@
 	}
 }
 
+static gboolean
+output_callers_xml (MethodProfile *p) {
+	char *m;
+	guint total_callers, percent;
+	int length;
+	CallerInfo *cinfo;
+	GSList *sorted, *tmps;
+
+	total_callers = 0;
+	for (cinfo = p->caller_info; cinfo; cinfo = cinfo->next)
+		total_callers += cinfo->count;
+	sorted = sort_caller_list (p->caller_info);
+	for (tmps = sorted; tmps; tmps = tmps->next) {
+		cinfo = tmps->data;
+		percent = (cinfo->count * 100)/total_callers;
+		if (percent < 1)
+			continue;
+		m = method_get_name (cinfo->caller);
+		length = fprintf (xml_file, "\t\t\t<caller count=\"%d\" name=\"%s\" percent=\"%d\"/>\n",
+				cinfo->count, m, percent);
+		g_free (m);
+		if (length < 0)
+			return FALSE;
+	}
+
+	return TRUE;
+}
+
+static guint
+total_allocated_mem (GList *proflist)
+{
+	GList *tmp;
+	NewobjProfile *p;
+	guint total = 0;
+
+	for (tmp = proflist; tmp; tmp = tmp->next) {
+		p = tmp->data;
+		total += p->count;
+	}
+
+	return total;
+}
+
+static gboolean
+output_newobj_profile_xml (GList *proflist)
+{
+	AllocInfo *ainfo;
+	GList *tmp;
+	GSList *sorted, *tmps;
+	MethodProfile *mp;
+	MonoClass *klass;
+	NewobjProfile *p;
+	const char *isarray;
+	char *m;
+	char buf [256];
+	guint total;
+	int length;
+
+	total = total_allocated_mem (proflist);
+	length = fprintf (xml_file, "\t<allocation mem=\"%d\">\n", total / 1024);
+	if (length < 0)
+		return FALSE;
+	for (tmp = proflist; tmp; tmp = tmp->next) {
+		p = tmp->data;
+		if (p->count < 50000)
+			continue;
+		mp = p->mp;
+		m = method_get_name (mp->method);
+		length = fprintf (xml_file, "\t\t<method size=\"%d\" name=\"%s\">\n", p->count / 1024, m);
+		g_free (m);
+		if (length < 0)
+			return FALSE;
+		sorted = sort_alloc_list (mp->alloc_info);
+		for (tmps = sorted; tmps; tmps = tmps->next) {
+			ainfo = tmps->data;
+			if (ainfo->mem < 50000)
+				continue;
+			klass = ainfo->klass;
+			if (klass->rank) {
+				isarray = "[]";
+				klass = klass->element_class;
+			} else {
+				isarray = "";
+			}
+			g_snprintf (buf, sizeof (buf), "%s.%s%s",
+					klass->name_space, klass->name, isarray);
+			length = fprintf (xml_file, "\t\t\t<alloc count=\"%d\" mem=\"%d\" name=\"%s\" />\n",
+					ainfo->count, ainfo->mem / 1024, buf);
+			if (length < 0)
+				return FALSE;
+		}
+		if (!output_callers_xml (mp) || fprintf (xml_file, "\t\t</method>\n") < 0)
+			return FALSE;
+	}
+
+	length = fprintf (xml_file, "\t</allocation>\n");
+
+	return (length < 0)?FALSE:TRUE;
+}
+
 static void
 output_newobj_profile (GList *proflist)
 {
@@ -1003,13 +1160,87 @@
 }
 
 static void
-simple_shutdown (MonoProfiler *prof)
+profiler_xml_error ()
+{
+	g_error ("Error writing %s.\n", profiler_xml_file);
+}
+
+static void
+simple_shutdown_xml (MonoProfiler *prof)
 {
+	gboolean errors;
+	GList *profile = NULL;
+	GSList *tmp;
+	MonoProfiler *tprof;
+	char *str;
+	int length;
+
+	if (!(xml_file = fopen (profiler_xml_file, "w"))) {
+		g_error ("Unable to create profile data in %s", profiler_xml_file);
+		return;
+	}
+
+	for (tmp = prof->per_thread; tmp; tmp = tmp->next) {
+		tprof = tmp->data;
+		merge_thread_data (prof, tprof);
+	}
+	length = fprintf (xml_file, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n<profile methods=\"%d\" total=\"%g\">\n",
+			prof->methods_jitted, prof->jit_time);
+	if (length < 0) {
+		profiler_xml_error ();
+		return;
+	}
+	
+	if (prof->max_jit_method) {
+		str = method_get_name (prof->max_jit_method);
+		length = fprintf (xml_file, "\t<slowest name=\"%s\" time=\"%g\" />\n", str, prof->max_jit_time);
+		g_free (str);
+		if (length < 0) {
+			profiler_xml_error ();
+			return;
+		}
+	}
+	
+	g_hash_table_foreach (prof->methods, (GHFunc)build_profile, &profile);
+	errors = output_profile_xml (profile);
+	g_list_free (profile);
+	profile = NULL;
+
+	if (!errors) {
+		profiler_xml_error ();
+		return;
+	}
+	
+	g_hash_table_foreach (prof->methods, (GHFunc)build_newobj_profile, &profile);
+	errors = output_newobj_profile_xml (profile);
+	g_list_free (profile);
+
+	if (!errors) {
+		profiler_xml_error ();
+		return;
+	}
+
+	length = fprintf (xml_file, "</profile>");
+	if (length < 0)
+		profiler_xml_error ();
+
+	fclose (xml_file);
+	
+}
+
+static void
+simple_shutdown (MonoProfiler *prof)
+{	
 	GList *profile = NULL;
 	MonoProfiler *tprof;
 	GSList *tmp;
 	char *str;
 
+	if (profiler_xml_file && strcmp (profiler_xml_file, "")) {
+		simple_shutdown_xml (prof);
+		return;
+	}
+
 	for (tmp = prof->per_thread; tmp; tmp = tmp->next) {
 		tprof = tmp->data;
 		merge_thread_data (prof, tprof);
@@ -1056,11 +1287,17 @@
 			else
 			   if (!strcmp (arg, "-alloc"))
 				   flags &= ~MONO_PROFILE_ALLOCATIONS;
-			   else {
-				   fprintf (stderr, "profiler : Unknown argument '%s'.\n", arg);
-				   return;
-			   }
+			   else
+				   if (!strcmp (arg, "xml"))
+					   profiler_xml_file = "profile.xml";
+				   else if (!strncmp (arg, "xml=", 4))
+					   profiler_xml_file = arg + 4;
+				   else {
+					   fprintf (stderr, "profiler : Unknown argument '%s'.\n", arg);
+					   return;
+				   }
 		}
+
 	}
 
 	prof = create_profiler ();
_______________________________________________
Mono-devel-list mailing list
Mono-devel-list@lists.ximian.com
http://lists.ximian.com/mailman/listinfo/mono-devel-list

Reply via email to