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.
*/
signature.asc
Description: Toto je digitálně podepsaná část zprávy
