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)
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.