Subject: bug#15876: 24.3.50; Highly degraded performance between rev 114715 and 115006

From: Dmitry Antipov <[email-masked]>
Date: Thu, 05 Dec 2013 10:29:45 +0400

On 12/04/2013 09:53 PM, Eli Zaretskii wrote:

 > What kind of information do I need to collect on Windows to make it
 > clear where the problem is?  Can you suggest some code that would
 > collect the necessary information, or ideas for writing such code?
 > (It's inconvenient to collect the data in GDB, since many objects are
 > marked at this point, and printing them from GDB crashes Emacs.)

OK, let's try the following steps.

1. Apply attached patch and rebuild.
2. Run emacs -Q, then M-x insert-char 25b7 and M-x describe-char.
    Now you should know the C pointer to font object which is used
    to display right-pointing triangle (underlined red on screenshot).
3. Insert GDB breakpoints to fprintf, move cursor, do some basic editing
    around the triangle and run M-x garbage-collect few times.  An
    interesting font object should be either marked or swept; if it's
    markerd, you should hit the breakpoint "GCX: mark interesting font Y".
    For my --without-xft build, M-x garbage-collect always shows that an
    interesting font object is marked in expected way - via face cache. E.g.:

(gdb) bt 8
#0  __fprintf (stream=0x3869dbb1e0 <_IO_2_1_stderr_>, format=0x6cf620 "GC%ld: mark interesting font %p\n") at fprintf.c:27
#1  0x00000000005c7269 in mark_vectorlike (ptr=0xd7c8b8) at ../../trunk/src/alloc.c:5745
#2  0x00000000005c75a4 in mark_face_cache (c=0x11456b0) at ../../trunk/src/alloc.c:5838
#3  0x00000000005c7b43 in mark_object (arg=...) at ../../trunk/src/alloc.c:6014
#4  0x00000000005c7288 in mark_vectorlike (ptr=0x127d4f8) at ../../trunk/src/alloc.c:5754
#5  0x00000000005c7baa in mark_object (arg=...) at ../../trunk/src/alloc.c:6031
#6  0x00000000005c7288 in mark_vectorlike (ptr=0xcf3230) at ../../trunk/src/alloc.c:5754
#7  0x00000000005c7457 in mark_buffer (buffer=0xcf3230) at ../../trunk/src/alloc.c:5805
(More stack frames follow...)

Dmitry

=== modified file 'src/alloc.c'
--- src/alloc.c	2013-12-01 22:33:13 +0000
+++ src/alloc.c	2013-12-05 06:10:49 +0000
@@ -2877,7 +2877,12 @@
   if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT)
       && ((vector->header.size & PSEUDOVECTOR_SIZE_MASK)
 	  == FONT_OBJECT_MAX))
-    ((struct font *) vector)->driver->close ((struct font *) vector);
+    {
+      if (((struct font *) vector)->debug)
+	fprintf (stderr, "GC%ld: free interesting font %p\n",
+		 gcs_done, vector);
+      ((struct font *) vector)->driver->close ((struct font *) vector);
+    }
 }
 
 /* Reclaim space used by unmarked vectors.  */
@@ -5733,6 +5738,14 @@
   if (size & PSEUDOVECTOR_FLAG)
     size &= PSEUDOVECTOR_SIZE_MASK;
 
+  if (FONT_OBJECT_P (make_lisp_ptr (ptr, Lisp_Vectorlike)))
+    {
+      struct font *f = (struct font *) ptr;
+      if (f->debug)
+	fprintf (stderr, "GC%ld: mark interesting font %p\n",
+		 gcs_done, f);
+    }
+
   /* Note that this size is not the memory-footprint size, but only
      the number of Lisp_Object fields that we should trace.
      The distinction is used e.g. by Lisp_Process which places extra

=== modified file 'src/font.c'
--- src/font.c	2013-12-04 13:08:30 +0000
+++ src/font.c	2013-12-05 06:00:56 +0000
@@ -188,6 +188,7 @@
   int i;
 
   XSETFONT (font_object, font);
+  font->debug = 0;
 
   if (! NILP (entity))
     {
@@ -196,6 +197,7 @@
       if (! NILP (AREF (entity, FONT_EXTRA_INDEX)))
 	font->props[FONT_EXTRA_INDEX]
 	  = Fcopy_alist (AREF (entity, FONT_EXTRA_INDEX));
+      font->props[FONT_ENTITY_INDEX] = entity;
     }
   if (size > 0)
     font->props[FONT_SIZE_INDEX] = make_number (pixelsize);
@@ -4189,7 +4191,7 @@
 the consecutive wildcards are folded into one.  */)
   (Lisp_Object font, Lisp_Object fold_wildcards)
 {
-  char name[256];
+  char name[256 + 32];
   int namelen, pixel_size = 0;
 
   CHECK_FONT (font);
@@ -4202,7 +4204,11 @@
 	  && SDATA (font_name)[0] == '-')
 	{
 	  if (NILP (fold_wildcards))
-	    return font_name;
+	    {
+	      XFONT_OBJECT (font)->debug = 1;
+	      return make_formatted_string
+		(name, "%s (%p)", SSDATA (font_name), XFONT_OBJECT (font));
+	    }
 	  strcpy (name, SSDATA (font_name));
 	  namelen = SBYTES (font_name);
 	  goto done;

=== modified file 'src/font.h'
--- src/font.h	2013-12-04 13:35:41 +0000
+++ src/font.h	2013-12-05 05:59:31 +0000
@@ -285,6 +285,8 @@
 
   /* Beyond here, there should be no more Lisp_Object components.  */
 
+  int debug;
+
   /* Minimum and maximum glyph widths, in pixels.  Some font backends,
      such as xft, lack the information to easily compute minimum and
      maximum widths over all characters; in that case, these values