Hi Panu et al, attached are two patches to make dependency solving faster/more correct. The first one switches the "installed file conflicts" cache from complete file names to base names, to make fingerprinting work for them.
The second one is the more interesing one, it adds a "installed file requires" cache. This cache is only created at the start of rpmtsCheck(), so it is most useful for big transactions. It is used to prune the filelist of the erased packages. Some numbers from my system: $ rpm -ql ddd | wc -l 51 $ rpm -ql kernel-source | wc -l 31128 With cold caches: - erase ddd complete dependency check: 27ms - erase ddd with requires cache cache creation: 16ms, complete dependency check: 30ms - erase kernel-source complete dependency check: 72ms - erase kernel-source with requires cache cache creation: 16ms, complete dependency check: 33ms With hot caches: - erase ddd complete dependency check: 0ms - erase ddd with requires cache cache creation: 2ms, complete dependency check: 2ms - erase kernel-source complete dependency check: 44ms - erase kernel-source with requires cache cache creation: 2ms, complete dependency check: 8ms So it's a very little bit slower for small packages, but helps a lot for big packages or big transactions. Cheers, Michael. -- Michael Schroeder m...@suse.de SUSE LINUX Products GmbH, GF Jeff Hawn, HRB 16746 AG Nuernberg main(_){while(_=~getchar())putchar(~_-1/(~(_|32)/13*2-11)*13);}
>From 68a2868e53a94147aa95bcd8796c310663cd16fc Mon Sep 17 00:00:00 2001 From: Michael Schroeder <m...@suse.de> Date: Wed, 6 Aug 2014 13:21:08 +0200 Subject: [PATCH 1/2] Put basenames in the conflict dependency cache This makes the fingerprinting code work for file conflicts of installed packages. --- lib/depends.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/lib/depends.c b/lib/depends.c index 7fd3986..3017cd2 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -754,6 +754,7 @@ int rpmtsCheck(rpmts ts) dcache = depCacheCreate(5001, rstrhash, strcmp, (depCacheFreeKey)rfree, NULL); + /* build cache of all file conflicts dependencies */ confcache = conflictsCacheCreate(257, rstrhash, strcmp, (depCacheFreeKey)rfree); if (confcache) { @@ -765,9 +766,15 @@ int rpmtsCheck(rpmts ts) char *k; if (!key || keylen == 0 || key[0] != '/') continue; - k = rmalloc(keylen + 1); - memcpy(k, key, keylen); - k[keylen] = 0; + while (keylen > 1 && (k = memchr(key + 1, '/', keylen - 1))) { + keylen -= k - key; + key += k - key; + } + if (keylen <= 1) + continue; + k = rmalloc(keylen); + memcpy(k, key + 1, keylen - 1); + k[keylen - 1] = 0; conflictsCacheAddEntry(confcache, k); } rpmdbIndexIteratorFree(ii); @@ -810,10 +817,9 @@ int rpmtsCheck(rpmts ts) rpmfiles files = rpmteFiles(p); rpmfi fi = rpmfilesIter(files, RPMFI_ITER_FWD); while (rpmfiNext(fi) >= 0) { - const char *fn = rpmfiFN(fi); - if (!conflictsCacheHasEntry(confcache, fn)) + if (!conflictsCacheHasEntry(confcache, rpmfiBN(fi))) continue; - checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, fn); + checkInstDeps(ts, dcache, p, RPMTAG_CONFLICTNAME, rpmfiFN(fi)); } rpmfiFree(fi); rpmfilesFree(files); -- 1.8.1.4
>From 8eb6ed8b8f09c86917005041b4203d615db69b4b Mon Sep 17 00:00:00 2001 From: Michael Schroeder <m...@suse.de> Date: Wed, 6 Aug 2014 13:27:56 +0200 Subject: [PATCH 2/2] Also build cache file requires of installed packages This speeds up erasure/update of packages with a large amount of files quite a bit. The cost of building the cache seems to be just a couple of msecs, and it just needs to be done once for the complete transaction set. --- lib/depends.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/depends.c b/lib/depends.c index 3017cd2..e871018 100644 --- a/lib/depends.c +++ b/lib/depends.c @@ -55,6 +55,13 @@ const int rpmFLAGS = RPMSENSE_EQUAL; #undef HASHTYPE #undef HTKEYTYPE +#define HASHTYPE requiresCache +#define HTKEYTYPE const char * +#include "rpmhash.H" +#include "rpmhash.C" +#undef HASHTYPE +#undef HTKEYTYPE + enum addOp_e { RPMTE_INSTALL = 0, RPMTE_UPGRADE = 1, @@ -740,6 +747,7 @@ int rpmtsCheck(rpmts ts) int rc = 0; depCache dcache = NULL; conflictsCache confcache = NULL; + requiresCache reqcache = NULL; (void) rpmswEnter(rpmtsOp(ts, RPMTS_OP_CHECK), 0); @@ -781,6 +789,33 @@ int rpmtsCheck(rpmts ts) } } + /* build cache of all file requires dependencies */ + reqcache = requiresCacheCreate(65537, rstrhash, strcmp, + (depCacheFreeKey)rfree); + if (reqcache) { + rpmdbIndexIterator ii = rpmdbIndexIteratorInit(rpmtsGetRdb(ts), RPMTAG_REQUIRENAME); + if (ii) { + char *key; + size_t keylen; + while ((rpmdbIndexIteratorNext(ii, (const void**)&key, &keylen)) == 0) { + char *k; + if (!key || keylen == 0 || key[0] != '/') + continue; + while (keylen > 1 && (k = memchr(key + 1, '/', keylen - 1))) { + keylen -= k - key; + key += k - key; + } + if (keylen <= 1) + continue; + k = rmalloc(keylen); + memcpy(k, key + 1, keylen - 1); + k[keylen - 1] = 0; + requiresCacheAddEntry(reqcache, k); + } + rpmdbIndexIteratorFree(ii); + } + } + /* * Look at all of the added packages and make sure their dependencies @@ -845,8 +880,11 @@ int rpmtsCheck(rpmts ts) } while (rpmfiNext(fi) >= 0) { - if (RPMFILE_IS_INSTALLED(rpmfiFState(fi))) + if (RPMFILE_IS_INSTALLED(rpmfiFState(fi))) { + if (!requiresCacheHasEntry(reqcache, rpmfiBN(fi))) + continue; checkInstDeps(ts, dcache, p, RPMTAG_REQUIRENAME, rpmfiFN(fi)); + } } rpmfiFree(fi); rpmfilesFree(files); @@ -856,6 +894,7 @@ int rpmtsCheck(rpmts ts) exit: depCacheFree(dcache); conflictsCacheFree(confcache); + requiresCacheFree(reqcache); (void) rpmswExit(rpmtsOp(ts, RPMTS_OP_CHECK), 0); -- 1.8.1.4
_______________________________________________ Rpm-maint mailing list Rpm-maint@lists.rpm.org http://lists.rpm.org/mailman/listinfo/rpm-maint