memprof -- memory profiler patches



Hi everybody!

I've been searching for a good memory profiler these days and I have
stopped at memprof.
It's a very cool application and it suits may needs.
However, it has some glitches.
I've downloaded the 0.6 version, it worked like a charm, but I
couldn't save the profiling in a file and send it to my boss.
So I've downloaded the trunk version from svn, but it crashed.

So I started hacking it.

I've created a patch for the 0.6 version to be able to save the
profile a file(Basically, I've taken the printing functions from the
trunk and used them, modifying a few bugs which were in trunk).

And I have also fixed some bugs on trunk, regarding the printing of
profiles.(Basically, I replaced name = caller->node->symbol;     with
  name = caller->node->symbol->name;  and now It prints the function
names and not junk :-) ).


You can make a release on the web for a 0.6.1 version that can print
the profiling to a file (this being the difference from 0.6), so
people can start using it.

Thank you very much for a great piece of software, and thank you for
it being open source, so I can fix myself the problems that I need to!

Keep up the very good work, and thanks again!






-- 
Ionut Grigorescu
--- memprof-0.6/profile.c	2004-01-23 13:22:01.000000000 +0200
+++ memprof-0.6_modif/profile.c	2008-06-26 16:59:12.000000000 +0300
@@ -20,6 +20,7 @@
 
 #include "profile.h"
 #include <glib.h>
+#include <errno.h>
 
 static GList *
 block_create_stack_list (Block *block, MPProcess *process, GHashTable *skip_hash)
@@ -435,71 +436,71 @@
     
     for (node = func->node; node != NULL; node = node->next)
     {
-	if (node->parent)
-	{
-	    if (!g_hash_table_lookup (callers_by_symbol, node->parent->symbol))
-	    {
-		ProfileFunc *caller = g_new (ProfileFunc, 1);
-		
-		caller->total = 0;
-		caller->self = 0;
-		caller->node = node->parent;
-		
-		g_hash_table_insert (
-		    callers_by_symbol, symbol_copy (node->parent->symbol), caller);
-		g_ptr_array_add (result, caller);
-	    }
-	}
-	else
-	{
-	    if (!spontaneous)
-	    {
-		spontaneous = g_new (ProfileFunc, 1);
-		spontaneous->total = 0;
-		spontaneous->self = 0;
-		spontaneous->node = NULL;
-		g_ptr_array_add (result, spontaneous);
-	    }
-	}
+		if (node->parent)
+		{
+			if (!g_hash_table_lookup (callers_by_symbol, node->parent->symbol))
+			{
+			ProfileFunc *caller = g_new (ProfileFunc, 1);
+			
+			caller->total = 0;
+			caller->self = 0;
+			caller->node = node->parent;
+			
+			g_hash_table_insert (
+				callers_by_symbol, symbol_copy (node->parent->symbol), caller);
+			g_ptr_array_add (result, caller);
+			}
+		}
+		else
+		{
+			if (!spontaneous)
+			{
+			spontaneous = g_new (ProfileFunc, 1);
+			spontaneous->total = 0;
+			spontaneous->self = 0;
+			spontaneous->node = NULL;
+			g_ptr_array_add (result, spontaneous);
+			}
+		}
     }
     
     for (node = func->node; node != NULL; node = node->next)
     {
-	ProfileNode *top_caller_node;
-	ProfileNode *top_callee_node;
-	ProfileFunc *caller;
-	ProfileNode *n;
+		ProfileNode *top_caller_node;
+		ProfileNode *top_callee_node;
+		ProfileFunc *caller;
+		ProfileNode *n;
 	
-	if (!node->parent)
-	{
-	    g_assert (spontaneous);
-	    caller = spontaneous;
-	}
-	else
-	    caller = g_hash_table_lookup (callers_by_symbol, node->parent->symbol);
-	
-	/* find topmost node/parent pair identical to this node/parent */
-	top_caller_node = node->parent;
-	top_callee_node = node;
-	for (n = node->parent; n && n->parent != NULL; n = n->parent)
-	{
-	    if (symbol_equal (n->symbol, node->symbol) &&
-		symbol_equal (n->parent->symbol, top_caller_node->symbol))
-	    {
-		top_caller_node = n->parent;
-		top_callee_node = n;
-	    }
-	}
-	if (!g_hash_table_lookup (marked_callers, top_caller_node))
-	{
-	    caller->total += top_callee_node->total;
-	    
-	    g_hash_table_insert (marked_callers, top_caller_node, GINT_TO_POINTER (1));
+		if (!node->parent)
+		{
+			g_assert (spontaneous);
+			caller = spontaneous;
+		}
+		else
+			caller = g_hash_table_lookup (callers_by_symbol, node->parent->symbol);
+		
+		/* find topmost node/parent pair identical to this node/parent */
+		top_caller_node = node->parent;
+		top_callee_node = node;
+		for (n = node->parent; n && n->parent != NULL; n = n->parent)
+		{
+			if (symbol_equal (n->symbol, node->symbol) &&
+				symbol_equal (n->parent->symbol, top_caller_node->symbol))
+				{
+				top_caller_node = n->parent;
+				top_callee_node = n;
+				}
+		}
+		if (!g_hash_table_lookup (marked_callers, top_caller_node))
+		{
+			caller->total += top_callee_node->total;
+			
+			g_hash_table_insert (marked_callers, top_caller_node, GINT_TO_POINTER (1));
+		}
+		
+		if (node->self > 0)
+			caller->self += node->self;
 	}
-	
-	if (node->self > 0)
-	    caller->self += node->self;
-    }
     
     g_hash_table_destroy (marked_callers);
     g_hash_table_destroy (callers_by_symbol);
@@ -507,19 +508,214 @@
     return result;
 }
 
+static gint
+compare_profile_funcs (gconstpointer a, gconstpointer b)
+{
+	const ProfileFunc *pa = * (const ProfileFunc**) a;
+	const ProfileFunc *pb = * (const ProfileFunc**) b;
+	if (pa->total > pb->total)
+		return -1;
+	if (pa->total < pb->total)
+		return 1;
+	return 0;
+}
+
+static GPtrArray *
+create_sorted_profile_funcs (GPtrArray *funcs)
+{
+	int i;
+	GPtrArray *functions;
+
+	functions = g_ptr_array_sized_new (funcs->len);
+
+	for (i = 0; i < funcs->len; ++i)
+		g_ptr_array_add (functions, funcs->pdata [i]);
+
+	g_ptr_array_sort (functions, compare_profile_funcs);
+
+	return functions;
+}
+
+static void
+output_callers (FILE* out, ProfileFunc *func)
+{
+	int i;
+	GPtrArray *profile_callers, *callers;
+
+	profile_callers = profile_func_create_caller_list (func);
+	callers         = create_sorted_profile_funcs (profile_callers);
+
+	fprintf (out, "  Callers (with count) that contribute at least for 1%%:\n");
+
+	for (i = 0; i < callers->len; ++i) {
+		const gchar* name;
+		unsigned int percent;
+		ProfileFunc *caller = callers->pdata [i];
+
+		if (caller->node) {
+			if (caller->node->symbol && caller->node->symbol->name)
+				name = caller->node->symbol->name;
+			else
+				name = "???";
+		}
+		else
+			name = "<spontaneous>";
+		percent = (caller->total * 100)/ func->total;
+		if (percent < 1)
+			continue;
+		fprintf (out, "    %10d %10d %3d %% %s\n", 
+				caller->self, caller->total, percent, name);
+	}
+
+	profile_caller_list_free (profile_callers);
+	g_ptr_array_free (callers, 1);
+}
+
+static gint
+compare_descendant_tree_nodes (gconstpointer a, gconstpointer b)
+{
+	const ProfileDescendantTreeNode *pa = * (const ProfileDescendantTreeNode **) a;
+	const ProfileDescendantTreeNode *pb = * (const ProfileDescendantTreeNode **) b;
+	if (pa->total > pb->total)
+		return -1;
+	if (pa->total < pb->total)
+		return 1;
+	return 0;
+}
+
+
+static GPtrArray *
+create_sorted_descendant_tree_nodes (GPtrArray *funcs)
+{
+	int i;
+	GPtrArray *functions;
+
+	functions = g_ptr_array_sized_new (funcs->len);
+
+	for (i = 0; i < funcs->len; ++i)
+		g_ptr_array_add (functions, funcs->pdata [i]);
+
+	g_ptr_array_sort (functions, compare_descendant_tree_nodes);
+
+	return functions;
+}
+static void
+output_descendants (FILE* out, ProfileFunc *func)
+{
+	int i;
+	ProfileDescendantTree *descendant_tree;
+	ProfileDescendantTreeNode *node;
+	GPtrArray *children;
+
+	descendant_tree = profile_func_create_descendant_tree (func);
+	node            = descendant_tree->roots->pdata [0];
+	children        = create_sorted_descendant_tree_nodes (node->children);
+
+	fprintf (out, "  Descendants (with count) that contribute at least for 1%%:\n");
+
+	for (i = 0; i < children->len; ++i) {
+		const gchar* name;
+		unsigned int percent;
+		ProfileDescendantTreeNode *child = children->pdata [i];
+
+		if (child->symbol && child->symbol->name) {
+			name = child->symbol->name;
+		}
+		else
+			name = "???";
+		percent = (child->total * 100)/ node->total;
+		if (percent < 1)
+			continue;
+		fprintf (out, "    %10d %10d %3d %% %s\n", 
+				child->self, child->total, percent, name);
+	}
+
+	profile_descendant_tree_free (descendant_tree);
+	g_ptr_array_free (children, 1);
+}
+
+
+
+static void
+output_profile_summary (FILE *out, guint n_bytes, GPtrArray *functions)
+{
+	int i;
+
+	fprintf (out, "      self      total total %% symbol\n");
+	fprintf (out, " --------- ---------- ------- ------------\n");
+
+	for (i = 0; i < functions->len; ++i) {
+		const gchar *name;
+		ProfileFunc *func = functions->pdata [i];
+		if (func->node->symbol && func->node->symbol->name)
+			name = func->node->symbol->name;
+		else
+			name = "???";
+		fprintf (out, "%10d %10d %5.2f %% %s\n", 
+				func->self, func->total,
+				func->total * 100.0 / (double) n_bytes,
+				name);
+	}
+}
+
+
+
+static void
+output_profile_details (FILE *out, guint n_bytes, GPtrArray *functions)
+{
+	int i;
+
+	for (i = 0; i < functions->len; ++i) {
+		const gchar *name;
+		ProfileFunc *func = functions->pdata [i];
+		if (func->node->symbol && func->node->symbol->name)
+			name = func->node->symbol->name;
+		else
+			name = "???";
+		fprintf (out, "########################\n");
+		fprintf (out, "%10d %10d %5.2f %% %s\n",
+				func->self, func->total,
+				func->total * 100.0 / (double) n_bytes,
+				name);
+		output_callers (out, func);
+		output_descendants (out, func);
+	}
+}
+
+
 void
 profile_caller_list_free	     (GPtrArray		     *caller_list)
 {
     int i;
-    
+
     for (i = 0; i < caller_list->len; ++i)
 	g_free (caller_list->pdata[i]);
-    
+
     g_ptr_array_free (caller_list, TRUE);
 }
 
+
 void
 profile_write (Profile *profile, const gchar *outfile)
 {
-    /* FIXME */
+   	FILE *out;
+	int i;
+	GPtrArray *functions;
+
+	out = fopen (outfile, "w");
+	if (!out) {
+		show_error (NULL, ERROR_MODAL, "Cannot open output file: %s\n",
+        	g_strerror (errno));
+		return;
+	}
+
+	functions = create_sorted_profile_funcs (profile->functions);
+
+	fprintf (out, "Total number of bytes profiled: %u\n", profile->n_bytes);
+
+	output_profile_summary (out, profile->n_bytes, functions);
+	output_profile_details (out, profile->n_bytes, functions);
+
+	g_ptr_array_free (functions, 1);
+	fclose (out);
 }
Index: profile.c
===================================================================
--- profile.c	(revision 437)
+++ profile.c	(working copy)
@@ -593,8 +593,8 @@
 		ProfileFunc *caller = callers->pdata [i];
 
 		if (caller->node) {
-			if (caller->node->symbol)
-				name = caller->node->symbol;
+			if (caller->node->symbol && caller->node->symbol->name)
+				name = caller->node->symbol->name;
 			else
 				name = "???";
 		}
@@ -630,8 +630,8 @@
 		unsigned int percent;
 		ProfileDescendantTreeNode *child = children->pdata [i];
 
-		if (child->symbol) {
-			name = child->symbol;
+		if (child->symbol && child->symbol->name) {
+			name = child->symbol->name;
 		}
 		else
 			name = "???";
@@ -657,8 +657,8 @@
 	for (i = 0; i < functions->len; ++i) {
 		const gchar *name;
 		ProfileFunc *func = functions->pdata [i];
-		if (func->node->symbol)
-			name = func->node->symbol;
+		if (func->node->symbol && func->node->symbol->name)
+			name = func->node->symbol->name;
 		else
 			name = "???";
 		fprintf (out, "%10d %10d %5.2f %% %s\n", 
@@ -676,8 +676,8 @@
 	for (i = 0; i < functions->len; ++i) {
 		const gchar *name;
 		ProfileFunc *func = functions->pdata [i];
-		if (func->node->symbol)
-			name = func->node->symbol;
+		if (func->node->symbol && func->node->symbol->name)
+			name = func->node->symbol->name;
 		else
 			name = "???";
 		fprintf (out, "########################\n");


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]