proj/portage:master commit in: lib/_emerge/
"Matt Turner" <[email protected]>
| Newsgroups | gmane.linux.gentoo.cvs |
|---|---|
| Message-ID | <1786739749.4a9e8f85add16b0374610ef573485532c5391482.mattst88@gentoo> |
commit: 4a9e8f85add16b0374610ef573485532c5391482
Author: Matt Turner <mattst88 <AT> gentoo <DOT> org>
AuthorDate: Thu Aug 13 21:21:53 2026 +0000
Commit: Matt Turner <mattst88 <AT> gentoo <DOT> org>
CommitDate: Fri Aug 14 20:35:49 2026 +0000
URL: https://gitweb.gentoo.org/proj/portage.git/commit/?id=4a9e8f85
depgraph: skip the dynamic-deps preload for already-applied packages
_load_vdb() runs once per depgraph, but frozen_config, and therefore the
FakeVartree it holds, is shared by every backtracking depgraph. Each new
depgraph re-walked every installed package, calling findname2() and
_pull_valid_cache() and re-applying the live ebuild dependencies that an
earlier pass had already applied.
The repeat passes are not merely redundant. The first pass rewrites
Package._metadata via aux_update(), so later passes derive dynamic deps
from an installed instance whose metadata is no longer the vdb's.
_aux_get_history already records which instances have had dynamic deps
applied, so use it to skip them. _sync() discards a changed instance via
cpv_discard(), which clears its entry, so an instance that really did
change is still re-derived.
An "emerge -p -uDN @world" resolve against a root with 1736 installed
packages ran the preload seven times per root before this change. Mean of
five interleaved runs of that resolve: 110.2s before, 101.5s after, with
run-to-run spread under 1.2s on either side.
Signed-off-by: Matt Turner <mattst88 <AT> gentoo.org>
lib/_emerge/FakeVartree.py | 11 +++++++++++
lib/_emerge/depgraph.py | 6 ++++++
2 files changed, 17 insertions(+)
diff --git a/lib/_emerge/FakeVartree.py b/lib/_emerge/FakeVartree.py
index b6a68df99..ef1247685 100644
--- a/lib/_emerge/FakeVartree.py
+++ b/lib/_emerge/FakeVartree.py
@@ -190,6 +190,17 @@ class FakeVartree(vartree):
aux_dict = dict(zip(aux_keys, self._aux_get(pkg.cpv, aux_keys)))
perform_global_updates(pkg.cpv, aux_dict, self.dbapi, self._global_updates)
+ def dynamic_deps_applied(self, pkg):
+ """True if the dynamic-deps apply has already run for ``pkg`` on this
+ instance.
+
+ depgraph._load_vdb() runs once per depgraph, but the FakeVartree lives
+ in frozen_config and is therefore shared by every backtracking depgraph.
+ The preload must not run twice over the same instance: the first pass
+ rewrites Package._metadata via aux_update(), so a second pass would be
+ deriving live dependencies for metadata that is no longer the vdb's."""
+ return pkg.cpv in self._aux_get_history
+
def dynamic_deps_preload(self, pkg, metadata):
if metadata is not None:
metadata = {k: metadata.get(k, "") for k in self._portdb_keys}
diff --git a/lib/_emerge/depgraph.py b/lib/_emerge/depgraph.py
index fe9e98bfa..86196c8f0 100644
--- a/lib/_emerge/depgraph.py
+++ b/lib/_emerge/depgraph.py
@@ -937,6 +937,12 @@ class depgraph:
for pkg in fake_vartree.dbapi:
self._dynamic_config._package_tracker.add_installed_pkg(pkg)
self._add_installed_sonames(pkg)
+ if fake_vartree.dynamic_deps_applied(pkg):
+ # An earlier depgraph sharing this FakeVartree already applied
+ # dynamic deps to this instance, and doing it again would only
+ # re-derive the same result from metadata that first pass
+ # rewrote.
+ continue
ebuild_path, repo_path = portdb.findname2(pkg.cpv, myrepo=pkg.repo)
if ebuild_path is None:
fake_vartree.dynamic_deps_preload(pkg, None)