You might have noticed a thread on the mailing list called "ports system
woes". The submitter pointed out an inefficiency in pkg_delete routine,
that parses the whole /var/db/pkg over and over again for every
dependency of a package being removed.

Attached is a patch by rdivacky that implements the idea of looking up
all the values in a single pass over /var/db/pkg content.

A trivial benchmark, wall times:

port with two dependencies (comms/obexapp)
before
0.083s

after
0.049s


port with 172 dependencies (graphics/agave)
before
8.404s
8.955s
11.734s

after
2.816s
2.690s
3.195s


The patch is not WARNS clean, that needs to be fixed. And I'd like a
review by someone with src commit bit.

-- 
Pav Lucistnik <[EMAIL PROTECTED]>
              <[EMAIL PROTECTED]>

42.7 percent of all statistics are made up on the spot.
Index: delete/perform.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/delete/perform.c,v
retrieving revision 1.41
diff -a -u -r1.41 perform.c
--- delete/perform.c	29 Jun 2004 19:06:41 -0000	1.41
+++ delete/perform.c	26 Mar 2008 15:47:29 -0000
@@ -123,16 +123,20 @@
 {
     FILE *cfile;
     char *deporigin, **depnames, home[FILENAME_MAX];
+    char **undirect_deps;
     PackingList p;
     int i, len;
     int isinstalled;
     /* support for separate pre/post install scripts */
-    int new_m = 0;
+    int new_m = 0, ud_count;
     const char *pre_script = DEINSTALL_FNAME;
     const char *post_script, *pre_arg, *post_arg;
     struct reqr_by_entry *rb_entry;
     struct reqr_by_head *rb_list;
 
+    depnames = NULL;
+    undirect_deps = NULL;
+
     if (!pkg || !(len = strlen(pkg)))
 	return 1;
     if (pkg[len - 1] == '/')
@@ -263,6 +267,7 @@
 	}
     }
 
+    ud_count = 0;
     for (p = Plist.head; p ; p = p->next) {
 	if (p->type != PLIST_PKGDEP)
 	    continue;
@@ -275,18 +280,28 @@
 	    printf(".\n");
 	}
 	if (!Fake) {
-	    depnames = (deporigin != NULL) ? matchbyorigin(deporigin, NULL) :
-					     NULL;
-	    if (depnames == NULL) {
-		depnames = alloca(sizeof(*depnames) * 2);
-		depnames[0] = p->name;
-		depnames[1] = NULL;
+	    if (deporigin == NULL) {
+		undepend(p->name, pkg);
+	    } else {
+	       undirect_deps = realloc(undirect_deps, (ud_count + 2) * sizeof(*undirect_deps));
+	       undirect_deps[ud_count] = deporigin;
+	       undirect_deps[ud_count + 1] = NULL;
+	       ud_count++;
 	    }
-	    for (i = 0; depnames[i] != NULL; i++)
-		undepend(depnames[i], pkg);
 	}
     }
 
+    if (undirect_deps != NULL) {
+	depnames = matchallbyorigin(undirect_deps, NULL);
+
+	free(undirect_deps);
+
+	/* Undepend all the dependancies at once */
+	for (i = 0; depnames[i] != NULL; i++)
+	   undepend(depnames[i], pkg);
+
+    }
+
     if (chdir(home) == FAIL) {
 	cleanup(0);
 	errx(2, "%s: unable to return to working directory %s!", __func__,
Index: lib/lib.h
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/lib.h,v
retrieving revision 1.56.2.2
diff -a -u -r1.56.2.2 lib.h
--- lib/lib.h	14 May 2006 07:06:37 -0000	1.56.2.2
+++ lib/lib.h	26 Mar 2008 15:47:29 -0000
@@ -216,6 +216,7 @@
 /* Query installed packages */
 char		**matchinstalled(match_t, char **, int *);
 char		**matchbyorigin(const char *, int *);
+char		**matchallbyorigin(const char **, int *);
 int		isinstalledpkg(const char *name);
 int		pattern_match(match_t MatchType, char *pattern, const char *pkgname);
 
Index: lib/match.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/pkg_install/lib/match.c,v
retrieving revision 1.19.8.2
diff -a -u -r1.19.8.2 match.c
--- lib/match.c	10 Nov 2007 22:04:31 -0000	1.19.8.2
+++ lib/match.c	26 Mar 2008 15:47:29 -0000
@@ -238,10 +238,10 @@
  * as a key for matching packages.
  */
 char **
-matchbyorigin(const char *origin, int *retval)
+matchallbyorigin(const char **origins, int *retval)
 {
     char **installed;
-    int i;
+    int i, j;
     static struct store *store = NULL;
 
     store = storecreate(store);
@@ -290,8 +290,9 @@
 		continue;
 	    cmd = plist_cmd(tmp + 1, &cp);
 	    if (cmd == PLIST_ORIGIN) {
-		if (csh_match(origin, cp, FNM_PATHNAME) == 0)
-		    storeappend(store, installed[i]);
+		for (j = 0; origins[j] != NULL; j++)
+		   if (csh_match(origins[j], cp, FNM_PATHNAME) == 0)
+		      storeappend(store, installed[i]);
 		break;
 	    }
 	}
@@ -307,6 +308,25 @@
 }
 
 /*
+ * Synopsis is similar to matchinstalled(), but use origin
+ * as a key for matching packages.
+ */
+char **
+matchbyorigin(const char *origin, int *retval)
+{
+   char **origins;
+   char **deps;
+
+   origins = malloc(sizeof(*origins) * 2);
+   origins[0] = origin;
+   origins[1] = NULL;
+
+   deps = matchallbyorigin(origins, retval);
+   free(origins);
+   return deps;
+}
+
+/*
  * Small linked list to memoize results of isinstalledpkg().  A hash table
  * would be faster but for n ~= 1000 may be overkill.
  */

Attachment: signature.asc
Description: Toto je digitálně podepsaná část zprávy

Reply via email to