memprof -- memory profiler patches

View: New views
1 Messages — Rating Filter:   Alert me  

memprof -- memory profiler patches

by Ionut Grigorescu-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

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

[save_profile_on_v06.patch]

--- 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);
 }


[func_names_on_trunk.patch]

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");


_______________________________________________
memprof-list mailing list
memprof-list@...
http://mail.gnome.org/mailman/listinfo/memprof-list