Subject: Performance improvement patch: chdir & namei

From: Steve Kinzler <[email-masked]>
Date: Wed, 1 May 91 13:24:04 -0500

Here's a patch that implements John's suggestion:

*   From John Mackin <[email-masked]>
*   Another performance improvement:
*   Another kludge which could cut down the namei overhead substantially is
*   to chdir() to the top of each facepath element and do the searching of
*   that part of the tree with relative pathnames from there, rather than
*   using absolute pathnames all the way from the root each time.
*   chdir()'ing is often very bad practice, but in an application that can't
*   possibly become interactive we don't have to be concerned.

The chdir() is only temporary -- in effect during the search subroutine,
so relative pathnames for -e script locations and facepath elements and
such still work as before.  I noted a 25% performance increase on a test
here.  Your mileage may vary -- we've got a convoluted path of symlinks
to get to /usr/local/faces on our system.

Steve Kinzler, [email-masked], 1 May 1991

*** main.c.old	Wed May  1 11:37:29 1991
--- main.c	Wed May  1 12:39:22 1991
***************
*** 22,27 ****
--- 22,28 ----
  #else
  #include <strings.h>
  #endif /* SYSV32 || hpux */
+ #include <sys/param.h>
  #include <sys/types.h>
  #include <sys/stat.h>
  #if !defined(mips) || defined(ultrix)
***************
*** 120,125 ****
--- 121,127 ----
  char peopfile[MAXLINE] ;    /* Name of the people/username file. */
  char *printer ;             /* Printer name to monitor. */
  char *progname ;            /* Name of this program. */
+ char *iwd ;                 /* Current working directory upon invocation. */
  char realcomm[MAXLINE] ;    /* Real community for this user. */
  char realname[MAXLINE] ;    /* Real username for this user. */
  char *spoolfile ;           /* Full pathname of users current mail. */
***************
*** 221,226 ****
--- 223,230 ----
  char *argv[] ;
  {
    read_str(&progname, argv[0]) ;  /* Save this programs name. */
+   iwd = (char *) getcwd(NULL, MAXPATHLEN);  /* Save current working dir. */
+   if (iwd == NULL) iwd = ".";
    init_graphics(&argc, argv) ;
    initialise() ;                  /* Set default values for various options. */
    load_resources() ;              /* Get resources from various places. */
***************
*** 578,584 ****
   *                 4 both.                     - ICON_BOTH.
   */
  
!   char *cptr, *icomm[3], *iuser[3] ;
    int i, ic, id, iu ;
  
    icomm[0] = community ;
--- 582,588 ----
   *                 4 both.                     - ICON_BOTH.
   */
  
!   char *cptr, *icomm[3], *iuser[3], *path ;
    int i, ic, id, iu ;
  
    icomm[0] = community ;
***************
*** 593,599 ****
  
    IF_DEBUG( FPRINTF(stderr, "make_iconname: %s[%s] ", community, user) ; )
    
!   for (id = 0; facepath[id] != NULL; id++)
      for (iu = 0; iuser[iu] != NULL; iu++)
        for (ic = 0; icomm[ic] != NULL; ic++)
          for (cptr = icomm[ic]; cptr != NULL; cptr = index(cptr, '.'))
--- 597,609 ----
  
    IF_DEBUG( FPRINTF(stderr, "make_iconname: %s[%s] ", community, user) ; )
    
!   for (id = 0; facepath[id] != NULL; id++) {
! 
! /* Chdir temporarily to the current facedir for faster namei accesses,
!  * if possible. */
! 
!     path = (chdir(facepath[id])) ? facepath[id] : ".";
! 
      for (iu = 0; iuser[iu] != NULL; iu++)
        for (ic = 0; icomm[ic] != NULL; ic++)
          for (cptr = icomm[ic]; cptr != NULL; cptr = index(cptr, '.'))
***************
*** 606,612 ****
                  cptr++ ;
                  if (*cptr == '\0') continue ;
                }
!             SPRINTF(iconname, "%s/%s/%s", facepath[id], cptr, iuser[iu]) ;
  
  /* If this file or directory isn't here, don't try any further for this one. */
  
--- 616,622 ----
                  cptr++ ;
                  if (*cptr == '\0') continue ;
                }
!             SPRINTF(iconname, "%s/%s/%s", path, cptr, iuser[iu]) ;
  
  /* If this file or directory isn't here, don't try any further for this one. */
  
***************
*** 615,637 ****
              if ((buf.st_mode & S_IFMT) == S_IFREG)
                {
                  old_style = 1 ;
                  IF_DEBUG( FPRINTF(stderr, "found as %s\n", iconname) ; )
                  return((enum min_type) (4 - (((ic & 1) << 1) + (iu & 1)))) ;
                }
              for (i = 0; i < maxtypes; i++)
                {
                  SPRINTF(iconname, "%s/%s/%s/%s", 
!                         facepath[id], cptr, iuser[iu], fname[i]) ;
                  if (stat(iconname, &buf) != -1)
                    {
                      IF_DEBUG( FPRINTF(stderr, "found as %s\n", iconname) ; )
  #ifdef NAMEUNKNOWN
                      if (EQUAL(iser[iu], "unknown")) STRCPY(user, "unknown") ;
  #endif /*NAMEUNKNOWN*/
                      return((enum min_type) (4 - (((ic & 1) << 1) + (iu & 1)))) ;
                    }
                }
            }
  
  /* Face icon not found, so the "blank face" should be used. */
  
--- 625,655 ----
              if ((buf.st_mode & S_IFMT) == S_IFREG)
                {
                  old_style = 1 ;
+                 SPRINTF(iconname, "%s/%s/%s", facepath[id], cptr, iuser[iu]) ;
                  IF_DEBUG( FPRINTF(stderr, "found as %s\n", iconname) ; )
+ 		chdir(iwd);
                  return((enum min_type) (4 - (((ic & 1) << 1) + (iu & 1)))) ;
                }
              for (i = 0; i < maxtypes; i++)
                {
                  SPRINTF(iconname, "%s/%s/%s/%s", 
!                         path, cptr, iuser[iu], fname[i]) ;
                  if (stat(iconname, &buf) != -1)
                    {
+                     SPRINTF(iconname, "%s/%s/%s/%s", 
+                             facepath[id], cptr, iuser[iu], fname[i]) ;
                      IF_DEBUG( FPRINTF(stderr, "found as %s\n", iconname) ; )
  #ifdef NAMEUNKNOWN
                      if (EQUAL(iser[iu], "unknown")) STRCPY(user, "unknown") ;
  #endif /*NAMEUNKNOWN*/
+ 		    chdir(iwd);
                      return((enum min_type) (4 - (((ic & 1) << 1) + (iu & 1)))) ;
                    }
                }
            }
+ 
+     chdir(iwd);
+   }
  
  /* Face icon not found, so the "blank face" should be used. */