GObject memory statistics
- From: Matthias Clasen <mclasen redhat com>
- To: performance-list gnome org
- Subject: GObject memory statistics
- Date: Tue, 04 Jul 2006 03:37:27 -0400
Ben Maurer has recently asked where the heap
goes that GTK+ apps use. Here is a very quick
patch to add some statistics to GObject.
Applying this to a e.g. gtk-demo yields
something like
[...]
49 GdkWindow, 4312 bytes
49 GdkWindowImplX11, 4900 bytes
117 GParamInt, 6084 bytes
190 GParamBoolean, 8360 bytes
13 GtkStyle, 9828 bytes
35 GtkRcStyle, 11620 bytes
53 PangoCairoFcFont, 12084 bytes
total: 106020 bytes
So, in terms of memory used by objects,
PangoCairoFcFont and GtkRcStyle are the
main offenders in this example.
Matthias
Index: gobject/gtype.c
===================================================================
RCS file: /cvs/gnome/glib/gobject/gtype.c,v
retrieving revision 1.88
diff -u -r1.88 gtype.c
--- gobject/gtype.c 15 Jun 2006 19:18:51 -0000 1.88
+++ gobject/gtype.c 4 Jul 2006 07:30:15 -0000
@@ -1518,6 +1518,90 @@
return node ? node->class : NULL;
}
+/* quick hack to collect some memory statistics */
+
+#include <signal.h>
+
+static GHashTable *type_stats = NULL;
+
+typedef struct
+{
+ GType type;
+ gint count;
+ gint size;
+} TypeStat;
+
+static void
+dump_stat (gpointer value, gpointer data)
+{
+ TypeStat *ts = (TypeStat*)value;
+ gint *total = (gint *)data;
+
+ g_print ("%d %s, %d bytes\n", ts->count, g_type_name (ts->type), ts->size);
+ *total += ts->size;
+}
+
+static gint
+compare_type_stats (gconstpointer a, gconstpointer b)
+{
+ TypeStat *as = (TypeStat *)a;
+ TypeStat *bs = (TypeStat *)b;
+
+ return as->size - bs->size;
+}
+
+static void
+collect_stats (gpointer key, gpointer value, gpointer data)
+{
+ GList **list = (GList **)data;
+
+ *list = g_list_insert_sorted (*list, value, compare_type_stats);
+}
+
+static void
+dump_type_stats (void)
+{
+ GList *stats = NULL;
+ gint total = 0;
+
+ g_hash_table_foreach (type_stats, collect_stats, &stats);
+ g_list_foreach (stats, dump_stat, &total);
+ g_print ("total: %d bytes\n", total);
+ g_list_free (stats);
+}
+
+static void
+change_instance_count (GType type, gint delta)
+{
+ TypeStat *data;
+ TypeNode *node;
+
+ node = lookup_type_node_I (type);
+ if (!type_stats)
+ {
+ g_print ("starting type statistics\n");
+ g_atexit (dump_type_stats);
+ signal (SIGUSR1, dump_type_stats);
+
+ type_stats = g_hash_table_new (g_direct_hash, g_direct_equal);
+ }
+
+ data = (TypeStat*) g_hash_table_lookup (type_stats, GINT_TO_POINTER (type));
+
+ if (!data)
+ {
+ data = g_new0 (TypeStat, 1);
+ data->type = type;
+ data->count = 0;
+ data->size = 0;
+ }
+
+ data->count += delta;
+ data->size += delta * type_total_instance_size_I (node);
+
+ g_hash_table_replace (type_stats, GINT_TO_POINTER (type), data);
+}
+
GTypeInstance*
g_type_create_instance (GType type)
{
@@ -1544,6 +1628,8 @@
class = g_type_class_ref (type);
total_size = type_total_instance_size_I (node);
+ change_instance_count (type, +1);
+
instance = g_slice_alloc0 (total_size);
if (node->data->instance.private_size)
@@ -1593,6 +1679,8 @@
return;
}
+ change_instance_count (class->g_type, -1);
+
instance->g_class = NULL;
#ifdef G_ENABLE_DEBUG
memset (instance, 0xaa, type_total_instance_size_I (node));
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]