Pixmap efficiency patch

Pavel Kankovsky <[email protected]>
Newsgroups gmane.comp.security.nessus.devel
Message-ID <[email protected]>
Nessus client appears to create an excessive number of redundant
GdkPixmap's, wasting X server resources and communication bandwidth (esp.
when it runs against a remote display). I made a patch that makes it cache
the most popular constant pixmaps in a parent window's properties. Here is
the comparison of the number of calls to gdk_pixmap_*create*() done by an
unpatched client and a patched client (started client, logged in, clicked
on every category in plugin list, opened and browsed a large part of a
saved report, exited client):

without patch: 403 calls
with patch:     18 calls

I suppose these numbers speak for themselves.

--Pavel Kankovsky aka Peak  [ Boycott Microsoft--http://www.vcnet.com/bms ]
"Resistance is futile. Open your source code and prepare for assimilation."
nessus-2.0.7-pixmap.patch (text/plain, 5.2 KB)
diff -urN nessus-2.0.7.orig/nessus-core/nessus/prefs_dialog/prefs_plugins.c nessus-2.0.7/nessus-core/nessus/prefs_dialog/prefs_plugins.c
--- nessus-2.0.7.orig/nessus-core/nessus/prefs_dialog/prefs_plugins.c	Thu Jan 23 19:05:54 2003
+++ nessus-2.0.7/nessus-core/nessus/prefs_dialog/prefs_plugins.c	Tue Sep 23 15:59:45 2003
@@ -105,18 +105,12 @@
 warning_sign(w)
  GtkWidget * w;
 {
- GdkPixmap * pm;
  GtkStyle * style;
- GdkBitmap * mask;
  GtkWidget * p;
  GtkWidget * ret;
  
  style = gtk_widget_get_style(w);
- pm = gdk_pixmap_create_from_xpm_d(w->window,
- 				     &mask,
-				     &style->bg[GTK_STATE_NORMAL],
-				     (gchar**)warning_small_xpm);
- p = gtk_pixmap_new(pm, mask);
+ p = make_pixmap(w, &style->bg[GTK_STATE_NORMAL], warning_small_xpm);
  
  ret = gtk_button_new();
  gtk_widget_set_usize(ret, 20, 20);
diff -urN nessus-2.0.7.orig/nessus-core/nessus/report.c nessus-2.0.7/nessus-core/nessus/report.c
--- nessus-2.0.7.orig/nessus-core/nessus/report.c	Thu Sep 26 22:57:54 2002
+++ nessus-2.0.7/nessus-core/nessus/report.c	Tue Sep 23 15:56:35 2003
@@ -149,9 +149,7 @@
  GtkWidget * label;
  GtkWidget * hbox;
  char ** pixdata = NULL;
- GdkPixmap * pixmap;
  GtkStyle * style;
- GdkBitmap * mask;
  GtkWidget * pixmapwid;
  switch(severity)
  {
@@ -169,10 +167,7 @@
 	break;
  }
  style = gtk_widget_get_style(window);
- pixmap = gdk_pixmap_create_from_xpm_d(window->window, &mask,
-            &style->bg[GTK_STATE_NORMAL],(gchar **)pixdata); 
-            
- pixmapwid = gtk_pixmap_new(pixmap, mask);
+ pixmapwid = make_pixmap(window, &style->bg[GTK_STATE_NORMAL], pixdata);
  hbox = gtk_hbox_new(FALSE,FALSE);
                
  label = gtk_label_new(name);
diff -urN nessus-2.0.7.orig/nessus-core/nessus/report_ng.c nessus-2.0.7/nessus-core/nessus/report_ng.c
--- nessus-2.0.7.orig/nessus-core/nessus/report_ng.c	Fri Mar 14 11:25:51 2003
+++ nessus-2.0.7/nessus-core/nessus/report_ng.c	Tue Sep 23 15:57:23 2003
@@ -751,9 +751,6 @@
  GtkWidget *widget = gtk_list_item_new();
  GtkWidget * box = gtk_hbox_new(FALSE, 3);
  GtkWidget * hostname;
- GdkColormap *colormap;
- GdkPixmap *gdkpixmap;
- GdkBitmap *mask;
  GtkWidget *pixmap;
  char * sort_key = gtk_object_get_data(GTK_OBJECT(list), "sort_key");
  char ** cat = NULL;
@@ -771,29 +768,16 @@
  
  if(cat)
  {
- colormap = gtk_widget_get_colormap (widget);
- gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask,
-                                                     NULL, (char**)cat);
-						     
- pixmap = gtk_pixmap_new (gdkpixmap, mask);
- gdk_pixmap_unref (gdkpixmap);
- gdk_bitmap_unref (mask);
- 
- gtk_box_pack_start(GTK_BOX(box), pixmap, FALSE, FALSE, 5);
- gtk_widget_show(pixmap);
+   pixmap = make_pixmap(list, NULL, cat);
+   gtk_box_pack_start(GTK_BOX(box), pixmap, FALSE, FALSE, 5);
+   gtk_widget_show(pixmap);
  }
  
  if((level = select_severity_pixmap(severity)))
  {
- colormap = gtk_widget_get_colormap (widget);
- gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (NULL, colormap, &mask,
-                                                     NULL, level);
- pixmap = gtk_pixmap_new (gdkpixmap, mask);
- gdk_pixmap_unref (gdkpixmap);
- gdk_bitmap_unref (mask);
- 
- gtk_box_pack_start(GTK_BOX(box), pixmap, FALSE, FALSE, 5);
- gtk_widget_show(pixmap);
+   pixmap = make_pixmap(list, NULL, level);
+   gtk_box_pack_start(GTK_BOX(box), pixmap, FALSE, FALSE, 5);
+   gtk_widget_show(pixmap);
  }
  
  t = strchr(name, '\r');
diff -urN nessus-2.0.7.orig/nessus-core/nessus/xstuff.c nessus-2.0.7/nessus-core/nessus/xstuff.c
--- nessus-2.0.7.orig/nessus-core/nessus/xstuff.c	Mon Aug 26 20:58:07 2002
+++ nessus-2.0.7/nessus-core/nessus/xstuff.c	Tue Sep 23 16:14:48 2003
@@ -57,4 +57,42 @@
  gtk_main_quit();
  nessus_exit(0);
 }
+
+struct pixmap_and_mask
+{
+  GdkPixmap *pixmap;
+  GdkBitmap *mask;
+};
+
+static void
+pixmap_and_mask_destroy_notify(gpointer p)
+{
+  gdk_pixmap_unref(((struct pixmap_and_mask *) p)->pixmap);
+  gdk_bitmap_unref(((struct pixmap_and_mask *) p)->mask);
+  g_free(p);
+}
+
+GtkWidget *
+make_pixmap
+    (GtkWidget *widget,
+     GdkColor  *transparent,
+     char      **xpm_data)
+{
+  struct pixmap_and_mask *p;
+  gchar name[64];
+  GdkColormap *colormap;
+
+  g_snprintf(name, sizeof(name), "N_PIXMAP_%lx", (long) xpm_data);
+  p = gtk_object_get_data(GTK_OBJECT(widget), name);
+  if (!p) {
+    p = g_malloc(sizeof(*p));
+    colormap = widget->window ? NULL : gtk_widget_get_colormap (widget);
+    p->pixmap = gdk_pixmap_colormap_create_from_xpm_d
+	(widget->window, colormap,
+	 &p->mask, transparent, (gchar **) xpm_data);
+    gtk_object_set_data_full
+        (GTK_OBJECT(widget), name, p, &pixmap_and_mask_destroy_notify);
+  }
+  return gtk_pixmap_new (p->pixmap, p->mask);
+}
 #endif
diff -urN nessus-2.0.7.orig/nessus-core/nessus/xstuff.h nessus-2.0.7/nessus-core/nessus/xstuff.h
--- nessus-2.0.7.orig/nessus-core/nessus/xstuff.h	Fri May 24 12:36:30 2002
+++ nessus-2.0.7/nessus-core/nessus/xstuff.h	Tue Sep 23 15:56:16 2003
@@ -23,4 +23,5 @@
 void close_display();
 int close_window(GtkWidget * , GtkWidget * );
 int delete_event(GtkWidget * nul, void * data);
+GtkWidget *make_pixmap(GtkWidget *, GdkColor *, char **);
 #endif
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.