Hi,

  I am a developper of the Enlightenment project, and during my work
on optimising it, I did find that _XimParseStringFile was accounting
for more than 30% of the time needed to get a window to show (under
valgrind). I am using an Ubuntu Intrepid and it provide a 630KB
"/usr/share/X11/locale/en_US.UTF-8/Compose". So it take a lot of time
to read and parse. I did write a small patch, attached, that use mmap
to read the file, this make _XimParseStringFile only account for 14%
of the time, a little bit better. I think that if it's a normal
behaviour to provide a 630KB file to parse (and it sounds like it is
as the last size from libX11 git is around 670KB), changing this file
to precompiled binary file format would be a better patch, sadly I
don't have the needed time to write it right now.

Regards,
-- 
Cedric BAIL
diff --git a/modules/im/ximcp/imLcPrs.c b/modules/im/ximcp/imLcPrs.c
index aa52c20..c136814 100644
--- a/modules/im/ximcp/imLcPrs.c
+++ b/modules/im/ximcp/imLcPrs.c
@@ -42,6 +42,7 @@ OR PERFORMANCE OF THIS SOFTWARE.
 #include "Xlcint.h"
 #include "Ximint.h"
 #include <sys/stat.h>
+#include <sys/mman.h>
 #include <stdio.h>
 
 extern int _Xmbstowcs(
@@ -79,36 +80,41 @@ extern int _Xmbstoutf8(
  */
 
 static int
+getic(const char *map,
+      unsigned long *position,
+      unsigned long max)
+{
+   if (*position < max)
+     return map[(*position)++];
+   return EOF;
+}
+
+static int
 nextch(
-    FILE *fp,
-    int *lastch)
+    const char *map,
+    unsigned long *position,
+    unsigned long max)
 {
     int c;
 
-    if (*lastch != 0) {
-	c = *lastch;
-	*lastch = 0;
-    } else {
-	c = getc(fp);
-	if (c == '\\') {
-	    c = getc(fp);
-	    if (c == '\n') {
-		c = getc(fp);
-	    } else {
-		ungetc(c, fp);
-		c = '\\';
-	    }
-	}
+    c = getic(map, position, max);
+    if (c == '\\') {
+       c = getic(map, position, max);
+       if (c == '\n') {
+	  c = getic(map, position, max);
+       } else {
+	  (*position)--;
+	  c = '\\';
+       }
     }
     return(c);
 }
 
 static void
-putbackch(
-    int c,
-    int *lastch)
+putbackch(unsigned long *position)
 {
-    *lastch = c;
+   if (*position <= 0) return;
+   (*position)--;
 }
 
 #define ENDOFFILE 0
@@ -131,17 +137,29 @@ putbackch(
 
 static int
 nexttoken(
-    FILE *fp,
     char *tokenbuf,
-    int *lastch)
+    unsigned long *tokenlength,
+    const char *map,
+    unsigned long *position,
+    unsigned long max)
 {
+    unsigned long l = 0;
     int c;
     int token;
     char *p;
     int i, j;
 
-    while ((c = nextch(fp, lastch)) == ' ' || c == '\t') {
-    }
+    c = EOF;
+    while (*position < max)
+      {
+	 c = map[(*position)++];
+	 if (c != ' '
+	     && c != '\t')
+	   break;
+      }
+    if (*position == max)
+      c = EOF;
+
     switch (c) {
       case EOF:
 	token = ENDOFFILE;
@@ -166,26 +184,31 @@ nexttoken(
 	break;
       case '"':
 	p = tokenbuf;
-	while ((c = nextch(fp, lastch)) != '"') {
+	l = 0;
+	while ((c = nextch(map, position, max)) != '"') {
 	    if (c == '\n' || c == EOF) {
-		putbackch(c, lastch);
+		putbackch(position);
 		token = ERROR;
 		goto string_error;
 	    } else if (c == '\\') {
-		c = nextch(fp, lastch);
+	        c = nextch(map, position, max);
 		switch (c) {
 		  case '\\':
 		  case '"':
 		    *p++ = c;
+		    l++;
 		    break;
 		  case 'n':
 		    *p++ = '\n';
+		    l++;
 		    break;
 		  case 'r':
 		    *p++ = '\r';
+		    l++;
 		    break;
 		  case 't':
 		    *p++ = '\t';
+		    l++;
 		    break;
 		  case '0':
 		  case '1':
@@ -196,20 +219,21 @@ nexttoken(
 		  case '6':
 		  case '7':
 		    i = c - '0';
-		    c = nextch(fp, lastch);
+		    c = nextch(map, position, max);
 		    for (j = 0; j < 2 && c >= '0' && c <= '7'; j++) {
 			i <<= 3;
 			i += c - '0';
-			c = nextch(fp, lastch);
+			c = nextch(map, position, max);
 		    }
-		    putbackch(c, lastch);
+		    putbackch(position);
 		    *p++ = (char)i;
+		    l++;
 		    break;
 		  case 'X':
 		  case 'x':
 		    i = 0;
 		    for (j = 0; j < 2; j++) {
-			c = nextch(fp, lastch);
+		        c = nextch(map, position, max);
  			i <<= 4;
 			if (c >= '0' && c <= '9') {
 			    i += c - '0';
@@ -218,7 +242,7 @@ nexttoken(
 			} else if (c >= 'a' && c <= 'f') {
 			    i += c - 'a' + 10;
 			} else {
-			    putbackch(c, lastch);
+			    putbackch(position);
 			    i >>= 4;
 			    break;
 		        }
@@ -228,25 +252,35 @@ nexttoken(
 		        goto string_error;
 		    }
 		    *p++ = (char)i;
+		    l++;
 		    break;
 		  case EOF:
-		    putbackch(c, lastch);
+		    putbackch(position);
 		    token = ERROR;
 		    goto string_error;
 		  default:
 		    *p++ = c;
+		    l++;
 		    break;
 		}
 	    } else {
 		*p++ = c;
+		l++;
 	    }
 	}
 	*p = '\0';
+	l++;
 	token = STRING;
 	break;
       case '#':
-	while ((c = nextch(fp, lastch)) != '\n' && c != EOF) {
+	c = EOF;
+	while (*position < max) {
+	    c = map[(*position)++];
+	    if (c == '\n')
+	      break;
 	}
+	if (*position == max)
+	    c = EOF;
 	if (c == '\n') {
 	    token = ENDOFLINE;
 	} else {
@@ -256,20 +290,24 @@ nexttoken(
       default:
 	if (isalnum(c) || c == '_' || c == '-') {
 	    p = tokenbuf;
+	    l = 1;
 	    *p++ = c;
-	    c = nextch(fp, lastch);
+	    c = nextch(map, position, max);
 	    while (isalnum(c) || c == '_' || c == '-') {
 		*p++ = c;
-		c = nextch(fp, lastch);
+		l++;
+		c = nextch(map, position, max);
 	    }
 	    *p = '\0';
-	    putbackch(c, lastch);
+	    l++;
+	    putbackch(position);
 	    token = KEY;
 	} else {
 	    token = ERROR;
 	}
 	break;
     }
+    *tokenlength = l;
 string_error:
     return(token);
 }
@@ -411,11 +449,14 @@ get_mb_string (Xim im, char *buf, KeySym ks)
 
 static int
 parseline(
-    FILE *fp,
     Xim   im,
-    char* tokenbuf)
+    char* tokenbuf,
+    const char *map,
+    unsigned long *position,
+    unsigned long max)
 {
     int token;
+    unsigned long tokenlength;
     DTModifier modifier_mask;
     DTModifier modifier;
     DTModifier tmp;
@@ -428,7 +469,6 @@ parseline(
     KeySym rhs_keysym = 0;
     char *rhs_string_mb;
     int l;
-    int lastch = 0;
     char local_mb_buf[MB_LEN_MAX+1];
     wchar_t local_wc_buf[LOCAL_WC_BUFSIZE], *rhs_string_wc;
     char local_utf8_buf[LOCAL_UTF8_BUFSIZE], *rhs_string_utf8;
@@ -443,7 +483,7 @@ parseline(
     int i, n;
 
     do {
-	token = nexttoken(fp, tokenbuf, &lastch);
+        token = nexttoken(tokenbuf, &tokenlength, map, position, max);
     } while (token == ENDOFLINE);
 
     if (token == ENDOFFILE) {
@@ -455,7 +495,7 @@ parseline(
     	if ((token == KEY) && (strcmp("include", tokenbuf) == 0)) {
             char *filename;
             FILE *infp;
-            token = nexttoken(fp, tokenbuf, &lastch);
+            token = nexttoken(tokenbuf, &tokenlength, map, position, max);
             if (token != KEY && token != STRING)
                 goto error;
             if ((filename = TransFileName(im, tokenbuf)) == NULL)
@@ -470,19 +510,19 @@ parseline(
 	} else if ((token == KEY) && (strcmp("None", tokenbuf) == 0)) {
 	    modifier = 0;
 	    modifier_mask = AllMask;
-	    token = nexttoken(fp, tokenbuf, &lastch);
+	    token = nexttoken(tokenbuf, &tokenlength, map, position, max);
 	} else {
 	    modifier_mask = modifier = 0;
 	    exclam = False;
 	    if (token == EXCLAM) {
 		exclam = True;
-		token = nexttoken(fp, tokenbuf, &lastch);
+		token = nexttoken(tokenbuf, &tokenlength, map, position, max);
 	    }
 	    while (token == TILDE || token == KEY) {
 		tilde = False;
 		if (token == TILDE) {
 		    tilde = True;
-		    token = nexttoken(fp, tokenbuf, &lastch);
+		    token = nexttoken(tokenbuf, &tokenlength, map, position, max);
 		    if (token != KEY)
 			goto error;
 		}
@@ -496,7 +536,7 @@ parseline(
 		} else {
 		    modifier |= tmp;
 		}
-		token = nexttoken(fp, tokenbuf, &lastch);
+		token = nexttoken(tokenbuf, &tokenlength, map, position, max);
 	    }
 	    if (exclam) {
 		modifier_mask = AllMask;
@@ -507,12 +547,12 @@ parseline(
 	    goto error;
 	}
 
-	token = nexttoken(fp, tokenbuf, &lastch);
+	token = nexttoken(tokenbuf, &tokenlength, map, position, max);
 	if (token != KEY) {
 	    goto error;
 	}
 
-	token = nexttoken(fp, tokenbuf, &lastch);
+	token = nexttoken(tokenbuf, &tokenlength, map, position, max);
 	if (token != GREATER) {
 	    goto error;
 	}
@@ -528,12 +568,12 @@ parseline(
 	n++;
 	if( n >= SEQUENCE_MAX )
 	    goto error;
-	token = nexttoken(fp, tokenbuf, &lastch);
+	token = nexttoken(tokenbuf, &tokenlength, map, position, max);
     } while (token != COLON);
 
-    token = nexttoken(fp, tokenbuf, &lastch);
+    token = nexttoken(tokenbuf, &tokenlength, map, position, max);
     if (token == STRING) {
-	l = strlen(tokenbuf) + 1;
+	l = tokenlength;
 	while (b->mbused + l > b->mbsize) {
 	    b->mbsize = b->mbsize ? b->mbsize * 1.5 : 1024;
 	    if (! (b->mb = Xrealloc (b->mb, b->mbsize)) )
@@ -542,13 +582,13 @@ parseline(
 	rhs_string_mb = &b->mb[b->mbused];
 	b->mbused    += l;
 	strcpy(rhs_string_mb, tokenbuf);
-	token = nexttoken(fp, tokenbuf, &lastch);
+	token = nexttoken(tokenbuf, &tokenlength, map, position, max);
 	if (token == KEY) {
 	    rhs_keysym = XStringToKeysym(tokenbuf);
 	    if (rhs_keysym == NoSymbol) {
 		goto error;
 	    }
-	    token = nexttoken(fp, tokenbuf, &lastch);
+	    token = nexttoken(tokenbuf, &tokenlength, map, position, max);
 	}
 	if (token != ENDOFLINE && token != ENDOFFILE) {
 	    goto error;
@@ -558,7 +598,7 @@ parseline(
 	if (rhs_keysym == NoSymbol) {
 	    goto error;
 	}
-	token = nexttoken(fp, tokenbuf, &lastch);
+	token = nexttoken(tokenbuf, &tokenlength, map, position, max);
 	if (token != ENDOFLINE && token != ENDOFFILE) {
 	    goto error;
 	}
@@ -648,7 +688,7 @@ parseline(
     return(n);
 error:
     while (token != ENDOFLINE && token != ENDOFFILE) {
-	token = nexttoken(fp, tokenbuf, &lastch);
+        token = nexttoken(tokenbuf, &tokenlength, map, position, max);
     }
     return(0);
 }
@@ -658,18 +698,26 @@ _XimParseStringFile(
     FILE *fp,
     Xim   im)
 {
-    char tb[8192];
     char* tbp;
+    char* map;
     struct stat st;
 
     if (fstat (fileno (fp), &st) != -1) {
 	unsigned long size = (unsigned long) st.st_size;
+	unsigned long position = 0;
+	char tb[8192];
+
 	if (size <= sizeof tb) tbp = tb;
 	else tbp = malloc (size);
 
-	if (tbp != NULL) {
-	    while (parseline(fp, im, tbp) >= 0) {}
-	    if (tbp != tb) free (tbp);
+	map = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED, fileno (fp), 0);
+
+	if (map != MAP_FAILED) {
+	   if (tbp != NULL) {
+	      while (parseline(im, tbp, map, &position, size) >= 0) {}
+	      if (tbp != tb) free (tbp);
+	   }
+	   munmap(map, st.st_size);
 	}
     }
 }
_______________________________________________
xorg-devel mailing list
[email protected]
http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to