Module Name:    src
Committed By:   sjg
Date:           Fri Jun  3 01:21:59 UTC 2016

Modified Files:
        src/usr.bin/make: main.c make.h meta.c nonints.h var.c

Log Message:
Add cached_realpath()

realpath(3) is expensive, and meta mode at least uses it extensively.
We use cached_realpath() to save the result of successful calls to
realpath(3) in a private variable context.

This improves the worst case performance (eg examining libc with
nothing to do) by a factor of 4.

Reviewed by: christos


To generate a diff of this commit:
cvs rdiff -u -r1.244 -r1.245 src/usr.bin/make/main.c
cvs rdiff -u -r1.98 -r1.99 src/usr.bin/make/make.h
cvs rdiff -u -r1.58 -r1.59 src/usr.bin/make/meta.c
cvs rdiff -u -r1.72 -r1.73 src/usr.bin/make/nonints.h
cvs rdiff -u -r1.207 -r1.208 src/usr.bin/make/var.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/usr.bin/make/main.c
diff -u src/usr.bin/make/main.c:1.244 src/usr.bin/make/main.c:1.245
--- src/usr.bin/make/main.c:1.244	Tue Apr  5 04:25:43 2016
+++ src/usr.bin/make/main.c	Fri Jun  3 01:21:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: main.c,v 1.244 2016/04/05 04:25:43 sjg Exp $	*/
+/*	$NetBSD: main.c,v 1.245 2016/06/03 01:21:59 sjg Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -69,7 +69,7 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: main.c,v 1.244 2016/04/05 04:25:43 sjg Exp $";
+static char rcsid[] = "$NetBSD: main.c,v 1.245 2016/06/03 01:21:59 sjg Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
@@ -81,7 +81,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 19
 #if 0
 static char sccsid[] = "@(#)main.c	8.3 (Berkeley) 3/19/94";
 #else
-__RCSID("$NetBSD: main.c,v 1.244 2016/04/05 04:25:43 sjg Exp $");
+__RCSID("$NetBSD: main.c,v 1.245 2016/06/03 01:21:59 sjg Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -979,7 +979,7 @@ main(int argc, char **argv)
 	    /*
 	     * A relative path, canonicalize it.
 	     */
-	    p1 = realpath(argv[0], mdpath);
+	    p1 = cached_realpath(argv[0], mdpath);
 	    if (!p1 || *p1 != '/' || stat(p1, &sb) < 0) {
 		p1 = argv[0];		/* realpath failed */
 	    }
@@ -1850,6 +1850,40 @@ usage(void)
 }
 
 
+/*
+ * realpath(3) can get expensive, cache results...
+ */
+char *
+cached_realpath(const char *pathname, char *resolved)
+{
+    static GNode *cache;
+    char *rp, *cp;
+
+    if (!pathname || !pathname[0])
+	return NULL;
+
+    if (!cache) {
+	cache = Targ_NewGN("Realpath");
+#ifndef DEBUG_REALPATH_CACHE
+	cache->flags = INTERNAL;
+#endif
+    }
+
+    rp = Var_Value(pathname, cache, &cp);
+    if (rp) {
+	/* a hit */
+	if (resolved)
+	    strlcpy(resolved, rp, MAXPATHLEN);
+	else
+	    resolved = bmake_strdup(rp);
+    } else {
+	if ((rp = realpath(pathname, resolved))) {
+	    Var_Set(pathname, rp, cache, 0);
+	}
+    }
+    return rp ? resolved : NULL;
+}
+
 int
 PrintAddr(void *a, void *b)
 {

Index: src/usr.bin/make/make.h
diff -u src/usr.bin/make/make.h:1.98 src/usr.bin/make/make.h:1.99
--- src/usr.bin/make/make.h:1.98	Thu Feb 18 18:29:14 2016
+++ src/usr.bin/make/make.h	Fri Jun  3 01:21:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: make.h,v 1.98 2016/02/18 18:29:14 christos Exp $	*/
+/*	$NetBSD: make.h,v 1.99 2016/06/03 01:21:59 sjg Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -183,6 +183,7 @@ typedef struct GNode {
 #define DONE_ALLSRC	0x40	/* We do it once only */
 #define CYCLE		0x1000  /* Used by MakePrintStatus */
 #define DONECYCLE	0x2000  /* Used by MakePrintStatus */
+#define INTERNAL	0x4000	/* Internal use only */
     enum enum_made {
 	UNMADE, DEFERRED, REQUESTED, BEINGMADE,
 	MADE, UPTODATE, ERROR, ABORTED

Index: src/usr.bin/make/meta.c
diff -u src/usr.bin/make/meta.c:1.58 src/usr.bin/make/meta.c:1.59
--- src/usr.bin/make/meta.c:1.58	Fri Jun  3 01:16:27 2016
+++ src/usr.bin/make/meta.c	Fri Jun  3 01:21:59 2016
@@ -1,4 +1,4 @@
-/*      $NetBSD: meta.c,v 1.58 2016/06/03 01:16:27 sjg Exp $ */
+/*      $NetBSD: meta.c,v 1.59 2016/06/03 01:21:59 sjg Exp $ */
 
 /*
  * Implement 'meta' mode.
@@ -251,7 +251,7 @@ meta_name(struct GNode *gn, char *mname,
      * basename as given to us.
      */
     if ((cp = strrchr(tname, '/'))) {
-	if (realpath(tname, buf)) {
+	if (cached_realpath(tname, buf)) {
 	    if ((rp = strrchr(buf, '/'))) {
 		rp++;
 		cp++;
@@ -433,7 +433,7 @@ meta_needed(GNode *gn, const char *dname
     }
 
     /* make sure these are canonical */
-    if (realpath(dname, objdir))
+    if (cached_realpath(dname, objdir))
 	dname = objdir;
 
     /* If we aren't in the object directory, don't create a meta file. */
@@ -1256,7 +1256,7 @@ meta_oodate(GNode *gn, Boolean oodate)
 		     * they are _expected_ to change.
 		     */
 		    if (*p == '/') {
-			realpath(p, fname1); /* clean it up */
+			cached_realpath(p, fname1); /* clean it up */
 			if (Lst_ForEach(metaIgnorePaths, prefix_match, fname1)) {
 #ifdef DEBUG_META_MODE
 			    if (DEBUG(META))
@@ -1341,7 +1341,7 @@ meta_oodate(GNode *gn, Boolean oodate)
 				oodate = TRUE;
 			    } else if (S_ISDIR(fs.st_mode)) {
 				/* Update the latest directory. */
-				realpath(p, latestdir);
+				cached_realpath(p, latestdir);
 			    }
 			} else if (errno == ENOENT && *p == '/' &&
 				   strncmp(p, cwd, cwdlen) != 0) {

Index: src/usr.bin/make/nonints.h
diff -u src/usr.bin/make/nonints.h:1.72 src/usr.bin/make/nonints.h:1.73
--- src/usr.bin/make/nonints.h:1.72	Thu Feb 18 20:25:08 2016
+++ src/usr.bin/make/nonints.h	Fri Jun  3 01:21:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: nonints.h,v 1.72 2016/02/18 20:25:08 sjg Exp $	*/
+/*	$NetBSD: nonints.h,v 1.73 2016/06/03 01:21:59 sjg Exp $	*/
 
 /*-
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -120,6 +120,7 @@ void execError(const char *, const char 
 char *getTmpdir(void);
 Boolean s2Boolean(const char *, Boolean);
 Boolean getBoolean(const char *, Boolean);
+char *cached_realpath(const char *, char *);
 
 /* parse.c */
 void Parse_Error(int, const char *, ...) MAKE_ATTR_PRINTFLIKE(2, 3);

Index: src/usr.bin/make/var.c
diff -u src/usr.bin/make/var.c:1.207 src/usr.bin/make/var.c:1.208
--- src/usr.bin/make/var.c:1.207	Fri Mar 11 15:12:39 2016
+++ src/usr.bin/make/var.c	Fri Jun  3 01:21:59 2016
@@ -1,4 +1,4 @@
-/*	$NetBSD: var.c,v 1.207 2016/03/11 15:12:39 matthias Exp $	*/
+/*	$NetBSD: var.c,v 1.208 2016/06/03 01:21:59 sjg Exp $	*/
 
 /*
  * Copyright (c) 1988, 1989, 1990, 1993
@@ -69,14 +69,14 @@
  */
 
 #ifndef MAKE_NATIVE
-static char rcsid[] = "$NetBSD: var.c,v 1.207 2016/03/11 15:12:39 matthias Exp $";
+static char rcsid[] = "$NetBSD: var.c,v 1.208 2016/06/03 01:21:59 sjg Exp $";
 #else
 #include <sys/cdefs.h>
 #ifndef lint
 #if 0
 static char sccsid[] = "@(#)var.c	8.3 (Berkeley) 3/19/94";
 #else
-__RCSID("$NetBSD: var.c,v 1.207 2016/03/11 15:12:39 matthias Exp $");
+__RCSID("$NetBSD: var.c,v 1.208 2016/06/03 01:21:59 sjg Exp $");
 #endif
 #endif /* not lint */
 #endif
@@ -531,7 +531,7 @@ VarAdd(const char *name, const char *val
     h = Hash_CreateEntry(&ctxt->context, name, NULL);
     Hash_SetValue(h, v);
     v->name = h->name;
-    if (DEBUG(VAR)) {
+    if (DEBUG(VAR) && (ctxt->flags & INTERNAL) == 0) {
 	fprintf(debug_file, "%s:%s = %s\n", ctxt->name, name, val);
     }
 }
@@ -1951,7 +1951,7 @@ VarRealpath(GNode *ctx MAKE_ATTR_UNUSED,
 	    Buf_AddByte(buf, vpstate->varSpace);
 	}
 	addSpace = TRUE;
-	rp = realpath(word, rbuf);
+	rp = cached_realpath(word, rbuf);
 	if (rp && *rp == '/' && stat(rp, &st) == 0)
 		word = rp;
 	

Reply via email to