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