[memprof: 41/76] merge rasterman's extra window
- From: Holger Hans Peter Freyther <hfreyther src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [memprof: 41/76] merge rasterman's extra window
- Date: Sun, 13 Jun 2010 03:41:41 +0000 (UTC)
commit acf1bf6e5d529b8b7b11e9bbe4bc21dcdeb1e8ea
Author: Holger Hans Peter Freyther <zecke selfish org>
Date: Sun Oct 25 07:45:00 2009 +0100
merge rasterman's extra window
Conflicts:
Makefile.am
src/gui.h
The commit comes from memprof-revised of atheme and has
been cleaned and merged.
Signed-off-by: Holger Hans Peter Freyther <zecke selfish org>
AUTHORS | 2 +
Makefile.am | 3 +-
src/detailwin.c | 397 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/gui.h | 43 ++++++
src/main.c | 41 +-----
5 files changed, 451 insertions(+), 35 deletions(-)
---
diff --git a/AUTHORS b/AUTHORS
index 2fc8603..804cbfd 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -2,3 +2,5 @@ Holger Hans Peter Freyther <zecke+memprof secretlabs de>
Owen Taylor <otaylor redhat com>
Kristian Rietveld <kris gtk org>
Soeren Sandmann <sandmann daimi au dk>
+Carsten Haitzler <raster rasterman com>
+
diff --git a/Makefile.am b/Makefile.am
index 53e0f1e..1548a35 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -33,7 +33,8 @@ memprof_SOURCES = \
src/elfparser.c \
src/binparser.h \
src/binparser.c \
- src/demangle.c
+ src/demangle.c \
+ src/detailwin.c
memprof_LDADD = $(MEMPROF_LIBS)
memprof_LDFLAGS = -export-dynamic
diff --git a/src/detailwin.c b/src/detailwin.c
new file mode 100644
index 0000000..200fbfd
--- /dev/null
+++ b/src/detailwin.c
@@ -0,0 +1,397 @@
+/* -*- mode: C; c-file-style: "linux" -*- */
+
+/* MemProf -- memory profiler and leak detector
+ * Copyright 2006 Carsten Haitzler
+ * Copyright 2009 Holger Hans Peter Freyther
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+/*====*/
+
+#define _GNU_SOURCE
+
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <regex.h>
+#include <signal.h>
+#include <sys/wait.h>
+
+
+#include <glade/glade.h>
+#include <gtk/gtk.h>
+
+#include "gui.h"
+#include "memprof.h"
+
+#define MEMSTATS 4096
+
+typedef struct _DW
+{
+ ProcessWindow *pwin;
+ GtkWidget *win, *da1, *da2;
+ guint memstats[MEMSTATS][2];
+} DW;
+
+static void
+dw_draw_memstats(DW *dw)
+{
+ GtkWidget *widget;
+ GdkPixmap *pixmap;
+ gint64 i, j, x, y, w, h, hh;
+
+ widget = dw->da1;
+ w = widget->allocation.width;
+ h = widget->allocation.height;
+ if (!widget->window) return;
+ pixmap = gdk_pixmap_new(widget->window, w, h, -1);
+ gdk_draw_rectangle(pixmap,
+ widget->style->base_gc[GTK_STATE_NORMAL],
+ TRUE,
+ 0, 0, w, h);
+ for (i = 0; i < MEMSTATS; i++)
+ {
+ x = w - i;
+ if (x < 0) break;
+ if (dw->pwin->usage_high > 0)
+ hh = (h * dw->memstats[i][1]) / dw->pwin->usage_high;
+ else
+ hh = 0;
+ y = h - hh;
+ gdk_draw_rectangle(pixmap,
+ widget->style->base_gc[GTK_STATE_SELECTED],
+ TRUE,
+ x, y, 1, hh);
+ if (dw->pwin->usage_high > 0)
+ hh = (h * dw->memstats[i][0]) / dw->pwin->usage_high;
+ else
+ hh = 0;
+ y = h - hh;
+ gdk_draw_rectangle(pixmap,
+ widget->style->text_gc[GTK_STATE_NORMAL],
+ TRUE,
+ x, y, 1, hh);
+ }
+ if (dw->pwin->usage_high > 0)
+ {
+ GdkGC *gc;
+
+ gc = gdk_gc_new(pixmap);
+ gdk_gc_copy(gc, widget->style->dark_gc[GTK_STATE_NORMAL]);
+ gdk_gc_set_line_attributes(gc, 0, GDK_LINE_ON_OFF_DASH,
+ GDK_CAP_BUTT, GDK_JOIN_MITER);
+ for (j = 0, i = 0; i < dw->pwin->usage_high; i += (256 * 1024), j++)
+ {
+ if (j > 3) j = 0;
+ y = h - ((i * h) / dw->pwin->usage_high);
+ if (j == 0)
+ gdk_draw_line(pixmap, widget->style->dark_gc[GTK_STATE_NORMAL],
+ 0, y, w, y);
+ else
+ gdk_draw_line(pixmap, gc,
+ 0, y, w, y);
+ }
+ gdk_gc_unref(gc);
+ }
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ pixmap, 0, 0, 0, 0, w, h);
+ gdk_pixmap_unref(pixmap);
+}
+
+typedef struct _Mem
+{
+ GtkWidget *widget;
+ GdkPixmap *pixmap;
+ guint w, h, bpp;
+ gulong mtotal;
+ GList *regs;
+} Mem;
+
+typedef struct _MemReg
+{
+ void *start;
+ unsigned long size;
+ int y, h;
+} MemReg;
+
+static void
+dw_draw_memmap_foreach(gpointer key, gpointer value, gpointer data)
+{
+ Mem *mem;
+ Block *block;
+ guint x, y, w, i;
+ GdkPixmap *pixmap;
+ GdkGC *gc;
+ gulong addr;
+ guint bpp, memw;
+ GList *l;
+ MemReg *reg;
+
+
+ mem = data;
+ block = value;
+ bpp = mem->bpp;
+ addr = (gulong)block->addr;
+ for (i = 0, l = mem->regs; l; l = l->next, i++)
+ {
+ reg = l->data;
+ if ((addr >= (gulong)reg->start) &&
+ (addr < (gulong)(reg->start + reg->size)))
+ break;
+ reg = NULL;
+ }
+ if (!reg) return;
+ addr = addr - (gulong)reg->start;
+ w = (gulong)(addr + block->size + (bpp / 2)) / bpp;
+ x = (gulong)(addr) / bpp;
+ w -= x;
+ memw = mem->w;
+ y = reg->y + (x / memw);
+ x -= (y * memw);
+ pixmap = mem->pixmap;
+ if (i & 0x1)
+ gc = mem->widget->style->fg_gc[GTK_STATE_PRELIGHT];
+ else
+ gc = mem->widget->style->fg_gc[GTK_STATE_NORMAL];
+ gdk_draw_rectangle(pixmap, gc, TRUE, x, y, w, 1);
+ if ((x + w) > mem->w)
+ gdk_draw_rectangle(pixmap, gc, TRUE, 0, y + 1, w - (memw - x), 1);
+}
+
+static void
+dw_draw_memmap(DW *dw)
+{
+ GtkWidget *widget;
+ GdkPixmap *pixmap;
+ guint w, h, y, bpl, i;
+ Mem mem;
+ GList *l;
+
+ widget = dw->da2;
+ w = widget->allocation.width;
+ h = widget->allocation.height;
+ if (!widget->window) return;
+ pixmap = gdk_pixmap_new(widget->window, w, h, -1);
+ gdk_draw_rectangle(pixmap,
+ widget->style->base_gc[GTK_STATE_NORMAL],
+ TRUE,
+ 0, 0, w, h);
+ mem.regs = NULL;
+ mem.widget = widget;
+ mem.pixmap = pixmap;
+ mem.w = w;
+ mem.h = h;
+ mem.mtotal = 0;
+ {
+ gchar buffer[1024];
+ FILE *in;
+ gchar perms[26];
+ gchar file[256];
+ gulong start, end;
+ guint major, minor, inode;
+
+ snprintf(buffer, 1023, "/proc/%d/maps", dw->pwin->process->pid);
+
+ in = fopen(buffer, "r");
+ while (fgets(buffer, 1023, in))
+ {
+ file[0] = 0;
+ int count = sscanf(buffer, "%lx-%lx %15s %*x %u:%u %u %255s",
+ &start, &end, perms, &major, &minor, &inode,
+ file);
+ if (count >= 5)
+ {
+ if ((!strcmp(perms, "rw-p")) && (inode == 0))
+ {
+ MemReg *reg;
+
+ reg = g_malloc(sizeof(MemReg));
+ reg->start = GSIZE_TO_POINTER(start);
+ reg->size = end - start;
+ mem.mtotal += reg->size;
+ mem.regs = g_list_append(mem.regs, reg);
+ }
+ }
+ }
+ fclose (in);
+ }
+ bpl = (mem.mtotal + h - 1) / h;
+ y = 0;
+ for (i = 0, l = mem.regs; l; l = l->next, i++)
+ {
+ MemReg *reg;
+
+ reg = l->data;
+ reg->h = ((reg->size * h) + bpl - 1) / mem.mtotal;
+ reg->y = y;
+ y += reg->h;
+ if (i & 0x1)
+ gdk_draw_rectangle(pixmap,
+ widget->style->base_gc[GTK_STATE_INSENSITIVE],
+ TRUE,
+ 0, reg->y, w, reg->h);
+ }
+ mem.bpp = (bpl + w - 1) / w;
+ if (mem.bpp < 1) mem.bpp = 1;
+
+ g_hash_table_foreach(dw->pwin->process->block_table,
+ dw_draw_memmap_foreach,
+ &mem);
+
+ for (l = mem.regs; l; l = l->next) g_free(l->data);
+ g_list_free(mem.regs);
+
+ gdk_draw_pixmap(widget->window,
+ widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
+ pixmap, 0, 0, 0, 0, w, h);
+ gdk_pixmap_unref(pixmap);
+}
+
+static gboolean
+on_da1_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
+{
+ DW *dw;
+
+ dw = user_data;
+ if (!dw->pwin->process) return FALSE;
+ dw_draw_memstats(dw);
+ return FALSE;
+}
+
+static gboolean
+on_da2_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
+{
+ DW *dw;
+
+ dw = user_data;
+ if (!dw->pwin->process) return FALSE;
+ dw_draw_memmap(dw);
+ return FALSE;
+}
+
+void
+dw_update(ProcessWindow *pwin)
+{
+ DW *dw;
+ guint i;
+
+ dw = pwin->detailwin_data;
+ if (!dw) return;
+ if (!pwin->process) return;
+ for (i = MEMSTATS - 1; i > 0; i--)
+ {
+ dw->memstats[i][0] = dw->memstats[i - 1][0];
+ dw->memstats[i][1] = dw->memstats[i - 1][1];
+ }
+ dw->memstats[0][0] = pwin->process->bytes_used;
+ dw->memstats[0][1] = pwin->usage_high;
+ dw_draw_memstats(dw);
+ dw_draw_memmap(dw);
+}
+
+void
+dw_init(ProcessWindow *pwin)
+{
+ DW *dw;
+
+ GtkWidget *win;
+ GtkWidget *notebook1;
+ GtkWidget *frame1;
+ GtkWidget *alignment1;
+ GtkWidget *da1;
+ GtkWidget *label1;
+ GtkWidget *frame2;
+ GtkWidget *alignment2;
+ GtkWidget *da2;
+ GtkWidget *label2;
+
+ dw = calloc(1, sizeof(DW));
+ pwin->detailwin_data = dw;
+ dw->pwin = pwin;
+
+ win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ gtk_window_set_title (GTK_WINDOW (win), "Extra Details");
+ gtk_window_set_default_size (GTK_WINDOW (win), 400, 300);
+
+ notebook1 = gtk_notebook_new ();
+ gtk_widget_show (notebook1);
+ gtk_container_add (GTK_CONTAINER (win), notebook1);
+ gtk_container_set_border_width (GTK_CONTAINER (notebook1), 4);
+
+ frame1 = gtk_frame_new (NULL);
+ gtk_widget_show (frame1);
+ gtk_container_add (GTK_CONTAINER (notebook1), frame1);
+ gtk_container_set_border_width (GTK_CONTAINER (frame1), 4);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_IN);
+
+ alignment1 = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_widget_show (alignment1);
+ gtk_container_add (GTK_CONTAINER (frame1), alignment1);
+
+ da1 = gtk_drawing_area_new ();
+ gtk_widget_show (da1);
+ gtk_container_add (GTK_CONTAINER (alignment1), da1);
+
+ label1 = gtk_label_new ("Time Graph");
+ gtk_widget_show (label1);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 0), label1);
+
+ frame2 = gtk_frame_new (NULL);
+ gtk_widget_show (frame2);
+ gtk_container_add (GTK_CONTAINER (notebook1), frame2);
+ gtk_container_set_border_width (GTK_CONTAINER (frame2), 4);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
+
+ alignment2 = gtk_alignment_new (0.5, 0.5, 1, 1);
+ gtk_widget_show (alignment2);
+ gtk_container_add (GTK_CONTAINER (frame2), alignment2);
+
+ da2 = gtk_drawing_area_new ();
+ gtk_widget_show (da2);
+ gtk_container_add (GTK_CONTAINER (alignment2), da2);
+
+ label2 = gtk_label_new ("Memory Usage Maps");
+ gtk_widget_show (label2);
+ gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook1), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook1), 1), label2);
+
+ dw->win = win;
+ dw->da1 = da1;
+ dw->da2 = da2;
+
+ g_signal_connect ((gpointer) da1, "expose_event",
+ G_CALLBACK (on_da1_expose_event),
+ dw);
+ g_signal_connect ((gpointer) da2, "expose_event",
+ G_CALLBACK (on_da2_expose_event),
+ dw);
+
+ gtk_widget_show(win);
+}
+
+void
+dw_shutdown(ProcessWindow *pwin)
+{
+ DW *dw;
+
+ dw = pwin->detailwin_data;
+ free(dw);
+ pwin->detailwin_data = NULL;
+}
diff --git a/src/gui.h b/src/gui.h
index 4232a9b..ed27c7e 100644
--- a/src/gui.h
+++ b/src/gui.h
@@ -20,10 +20,47 @@
*/
/*====*/
+#ifndef GUI_H
+
+#include "leakdetect.h"
+#include "profile.h"
#include "process.h"
+#include "server.h"
+
typedef struct _ProcessWindow ProcessWindow;
+struct _ProcessWindow {
+ MPProcess *process;
+ Profile *profile;
+ GSList *leaks;
+
+ GtkWidget *main_window;
+ GtkWidget *main_notebook;
+ GtkWidget *n_allocations_label;
+ GtkWidget *profile_status_label;
+ GtkWidget *bytes_per_label;
+ GtkWidget *total_bytes_label;
+
+ GtkWidget *profile_func_tree_view;
+ GtkWidget *profile_caller_tree_view;
+ GtkWidget *profile_descendants_tree_view;
+
+ GtkWidget *leak_block_tree_view;
+ GtkWidget *leak_stack_tree_view;
+
+ GtkWidget *usage_max_label;
+ GtkWidget *usage_area;
+
+ guint usage_max;
+ guint usage_high;
+ guint usage_leaked;
+
+ guint status_update_timeout;
+
+ void *detailwin_data;
+};
+
void tree_window_show (void);
void tree_window_add (ProcessWindow *window);
void tree_window_remove (ProcessWindow *window);
@@ -39,3 +76,9 @@ void process_window_maybe_detach (ProcessWindow *pwin);
gboolean hide_and_check_quit (GtkWidget *window);
void check_quit (void);
+
+void dw_init(ProcessWindow *pwin);
+void dw_shutdown(ProcessWindow *pwin);
+void dw_update(ProcessWindow *pwin);
+
+#endif
diff --git a/src/main.c b/src/main.c
index 63a96c7..5e421e3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -36,12 +36,8 @@
#include <regex.h>
-#include "leakdetect.h"
#include "gui.h"
#include "memprof.h"
-#include "process.h"
-#include "profile.h"
-#include "server.h"
#include "treeviewutils.h"
#include <string.h>
#include <stdlib.h>
@@ -49,34 +45,6 @@
#include <glib/gprintf.h>
#include "elfparser.h"
-struct _ProcessWindow {
- MPProcess *process;
- Profile *profile;
- GSList *leaks;
-
- GtkWidget *main_window;
- GtkWidget *main_notebook;
- GtkWidget *n_allocations_label;
- GtkWidget *profile_status_label;
- GtkWidget *bytes_per_label;
- GtkWidget *total_bytes_label;
-
- GtkWidget *profile_func_tree_view;
- GtkWidget *profile_caller_tree_view;
- GtkWidget *profile_descendants_tree_view;
-
- GtkWidget *leak_block_tree_view;
- GtkWidget *leak_stack_tree_view;
-
- GtkWidget *usage_max_label;
- GtkWidget *usage_area;
-
- guint usage_max;
- guint usage_high;
- guint usage_leaked;
-
- guint status_update_timeout;
-};
enum {
PROFILE_FUNC_NAME,
@@ -253,7 +221,8 @@ update_status (gpointer data)
pwin->usage_high = MAX (pwin->process->bytes_used, pwin->usage_high);
gtk_widget_queue_draw (pwin->usage_area);
-
+ dw_update(pwin);
+
return TRUE;
}
@@ -975,6 +944,7 @@ process_window_reset (ProcessWindow *pwin)
gtk_window_set_title (GTK_WINDOW (pwin->main_window), "MemProf");
gtk_widget_queue_draw (pwin->usage_area);
+ dw_update(pwin);
}
static void
@@ -1340,6 +1310,8 @@ process_window_free (ProcessWindow *pwin)
static void
process_window_destroy (ProcessWindow *pwin)
{
+ dw_shutdown(pwin);
+
if (pwin->status_update_timeout)
g_source_remove (pwin->status_update_timeout);
@@ -1585,7 +1557,8 @@ process_window_new (void)
glade_xml_signal_autoconnect (xml);
g_object_unref (G_OBJECT (xml));
-
+
+ dw_init(pwin);
return pwin;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]