[Evolution-hackers] memory bitmap patch




The patch attached will track the memory used by evolution as it is running, and then dump a greyscale bitmap which represents the memory used.  Each pixel represents 16 bytes of memory, and its intensity maps to how many bytes in that block is used, i.e. white means all bytes, black means none, grey means 8, etc.

Needs glibc.

May need x86.

Probably has bugs.

I whipped it up to see if evolution was generating particularly fragmentary memory use, since valgrind reported much different usage to top.  While it is quite fragmented, it doesn't look unusually so.

Index: shell/main.c
===================================================================
RCS file: /cvs/gnome/evolution/shell/main.c,v
retrieving revision 1.166
diff -u -p -r1.166 main.c
--- shell/main.c	23 Feb 2005 18:56:59 -0000	1.166
+++ shell/main.c	10 Mar 2005 03:32:39 -0000
@@ -113,6 +113,187 @@ static gint idle_cb (void *data);
 static char *default_component_id = NULL;
 static char *evolution_debug_log = NULL;
 
+
+/* memory map debugging */
+/* Prototypes for __malloc_hook, __free_hook */
+#include <malloc.h>
+#include <stdlib.h>
+     
+/* Prototypes for our hooks.  */
+static void my_init_hook (void);
+static void *my_malloc_hook (size_t, const void *);
+static void my_free_hook (void*, const void *);
+     
+/* Override initializing hook from the C library. */
+void (*__malloc_initialize_hook) (void) = my_init_hook;
+static void *old_malloc_hook;
+static void *old_free_hook;
+static size_t total;
+
+#define TOTALK (102400*2)
+#define TOTAL (TOTALK*1024)
+
+static unsigned char *base = (void *)-1;
+/* for every 4 bits, we record how many of the 16 bytes it represnts are used */
+static unsigned char bitmap[TOTAL/16/2];
+
+static void
+my_init_hook (void)
+{
+	old_malloc_hook = __malloc_hook;
+	old_free_hook = __free_hook;
+	__malloc_hook = my_malloc_hook;
+	__free_hook = my_free_hook;
+}
+     
+static void *
+my_malloc_hook (size_t size, const void *caller)
+{
+	void *result;
+	/* Restore all old hooks */
+	__malloc_hook = old_malloc_hook;
+	__free_hook = old_free_hook;
+	/* Call recursively */
+	result = malloc (size);
+
+	/* Save underlying hooks */
+	old_malloc_hook = __malloc_hook;
+	old_free_hook = __free_hook;
+
+#if 0
+	/* `printf' might call `malloc', so protect it too. */
+	printf ("malloc (%u) returns %p\n", (unsigned int) size, result);
+	/* Restore our own hooks */
+#endif
+	if (result != NULL) {
+		int off, i, bit, byte;
+
+		total += size;
+
+		if (base == (void *)-1) {
+			base = result;
+		} else if (((unsigned char *)result) < base) {
+			printf("result lower than base %p < %p\n", result, base);
+		}
+
+		off = (((unsigned char *)result)-base);
+		for (i=0;i<size;i++) {
+			bit = i+off;
+			byte = bit >> 5;
+			if (byte > 0 && byte < sizeof(bitmap)) {
+				unsigned char val = bitmap[byte];
+
+				if (bit & 0x10) {
+					if ((val & 0xf0) != 0xf0)
+						bitmap[byte] = (val & 0xf) | ((((val & 0xf0) >> 4) + 1) << 4);
+				} else {
+					if ((val & 0x0f) != 0x0f)
+						bitmap[byte] = (val & 0xf0) | ((val & 0x0f)+1);
+				}
+			}
+		}
+	}
+
+	__malloc_hook = my_malloc_hook;
+	__free_hook = my_free_hook;
+	return result;
+}
+     
+static void
+my_free_hook (void *ptr, const void *caller)
+{
+	/* Restore all old hooks */
+	__malloc_hook = old_malloc_hook;
+	__free_hook = old_free_hook;
+
+	if (ptr != NULL) {
+		int off, i, bit, byte;
+		size_t size;
+
+		if (base == (void *)-1) {
+			base = ptr;
+		} else if (((unsigned char *)ptr) < base) {
+		}
+
+		/* glibc malloc stores size immediately before allocated pointer (?) */
+		size = ((size_t *)ptr)[-1];
+
+		total -= size;
+
+		off = (((unsigned char *)ptr)-base);
+		for (i=0;i<size;i++) {
+			bit = i+off;
+			byte = bit >> 5;
+			if (byte > 0 && byte < sizeof(bitmap)) {
+				unsigned char val = bitmap[byte];
+
+				if (bit & 0x10) {
+					if ((val & 0xf0) != 0x00)
+						bitmap[byte] = (val & 0xf) | ((((val & 0xf0) >> 4) - 1) << 4);
+				} else {
+					if ((val & 0x0f) != 0x00)
+						bitmap[byte] = (val & 0xf0) | ((val & 0x0f)-1);
+				}
+			}
+		}
+	}
+
+	/* Call recursively */
+	free (ptr);
+	/* Save underlying hooks */
+	old_malloc_hook = __malloc_hook;
+	old_free_hook = __free_hook;
+	/* `printf' might call `free', so protect it too. */
+	/*printf ("freed pointer %p\n", ptr);*/
+	/* Restore our own hooks */
+	__malloc_hook = my_malloc_hook;
+	__free_hook = my_free_hook;
+}
+
+#include <stdio.h>
+
+static void
+dump_bm(void)
+{
+	int width, height, i, j;
+	FILE *out;
+	static int num = 0;
+	char filename[32];
+
+	sprintf(filename, "/tmp/bitmap.%03u.pnm", num++);
+	printf("writing '%s'\n", filename);
+	printf("total at exit: %u\n", total);
+
+	out = fopen(filename, "w");
+	if (out == NULL)
+		return;
+
+	width = 1024;
+	height = sizeof(bitmap)/2/width;
+	fprintf(out, "P5\n%d\n%d\n16\n", width, height);
+	for (i=0;i<height;i++) {
+		for (j=0;j<width/2;j++) {
+			unsigned char val = bitmap[i*width/2+j];
+
+			fprintf(out, "%c%c", val>>4, val&0x0f);
+		}
+	}
+	fclose(out);
+}
+
+static gboolean
+dump_timeout(void *data)
+{
+	dump_bm();
+
+	return TRUE;
+}
+
+/* end memory map debugging */
+
+
+
+
 static void
 no_windows_left_cb (EShell *shell, gpointer data)
 {
@@ -610,13 +791,17 @@ main (int argc, char **argv)
 	else
 #endif
 		g_idle_add (idle_cb, uri_list);	
-	
+
+	/*g_timeout_add(2000, dump_timeout, NULL);*/
+
 	bonobo_main ();
 	
 	e_icon_factory_shutdown ();
 	g_object_unref (program);
 	gnome_sound_shutdown ();
 	e_cursors_shutdown ();
+
+	dump_bm();
 	
 	return 0;
 }


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