libpkgconf: pkg: cache solutions for already solved dependency graph nodes

in almost all cases, we partially solve the dependency graph multiple times, which
just wastes resources.  if we record the solution to a given dependency node, further
iterations can make use of the previous solution without having to solve it again.

this is safe because all provides entries (including virtuals) are knowable prior to
solving the dependency graph the first time.

a nice side effect of this is that all packages are preloaded when querying
information about them (--cflags and related commands).
feature/tap-sh
William Pitcock 2017-12-05 17:34:01 -06:00
parent 44b4b126f3
commit 74d58d1b63
3 changed files with 17 additions and 5 deletions

View File

@ -132,6 +132,9 @@ pkgconf_dependency_free(pkgconf_list_t *list)
{
pkgconf_dependency_t *dep = node->data;
if (dep->match != NULL)
pkgconf_pkg_unref(NULL, dep->match);
if (dep->package != NULL)
free(dep->package);

View File

@ -87,6 +87,7 @@ struct pkgconf_dependency_ {
pkgconf_pkg_comparator_t compare;
char *version;
pkgconf_pkg_t *parent;
pkgconf_pkg_t *match;
};
struct pkgconf_tuple_ {

View File

@ -1273,6 +1273,12 @@ pkgconf_pkg_verify_dependency(pkgconf_client_t *client, pkgconf_dependency_t *pk
PKGCONF_TRACE(client, "trying to verify dependency: %s", pkgdep->package);
if (pkgdep->match != NULL)
{
PKGCONF_TRACE(client, "cached dependency: %s -> %s@%p", pkgdep->package, pkgdep->match->id, pkgdep->match);
return pkgconf_pkg_ref(client, pkgdep->match);
}
pkg = pkgconf_pkg_find(client, pkgdep->package);
if (pkg == NULL)
{
@ -1290,11 +1296,13 @@ pkgconf_pkg_verify_dependency(pkgconf_client_t *client, pkgconf_dependency_t *pk
if (pkg->id == NULL)
pkg->id = strdup(pkgdep->package);
if (pkgconf_pkg_comparator_impls[pkgdep->compare](pkg->version, pkgdep->version) == true)
return pkg;
if (eflags != NULL)
*eflags |= PKGCONF_PKG_ERRF_PACKAGE_VER_MISMATCH;
if (pkgconf_pkg_comparator_impls[pkgdep->compare](pkg->version, pkgdep->version) != true)
{
if (eflags != NULL)
*eflags |= PKGCONF_PKG_ERRF_PACKAGE_VER_MISMATCH;
}
else
pkgdep->match = pkgconf_pkg_ref(client, pkg);
return pkg;
}