Performance improvement patch: chdir & namei

Steve Kinzler (kinzler@iuvax.cs.indiana.edu)
Wed, 1 May 91 13:24:04 -0500

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

* From John Mackin <john@syd.dit.csiro.au>
* 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, kinzler@cs.indiana.edu, 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. */