memprof -- memory profiler patches
- From: "Ionut Grigorescu" <ionut grigorescu gmail com>
- To: gnome-love gnome org, memprof-list gnome org, otaylor redhat com
- Subject: memprof -- memory profiler patches
- Date: Thu, 26 Jun 2008 18:36:11 +0300
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]