commit:     5f0541c8739bd0342a94aa108e5101588eaefc16
Author:     Zac Medico <zmedico <AT> gentoo <DOT> org>
AuthorDate: Fri Nov 21 03:57:59 2014 +0000
Commit:     Zac Medico <zmedico <AT> gentoo <DOT> org>
CommitDate: Mon Nov 24 08:02:54 2014 +0000
URL:        
http://sources.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=5f0541c8

_select_pkg_highest_available: selective cache invalidation (530010)

Implement selective invalidation of cache for the
depgraph._select_pkg_highest_available method, so that the entire cache
is not discarded whenever a package is added to the graph. On one of my
computers with this patch, 'emerge -puvDN @world' takes 15% less time,
and results in 58% fewer _select_pkg_highest_available_imp calls.

X-Gentoo-Bug: 530010
X-Gentoo-Url: https://bugs.gentoo.org/show_bug.cgi?id=530010
Acked-by: Alexander Berntsen <bernalex <AT> gentoo.org>

---
 pym/_emerge/Package.py  | 18 ++++++++++++++++--
 pym/_emerge/depgraph.py | 14 +++++++++++++-
 2 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/pym/_emerge/Package.py b/pym/_emerge/Package.py
index a09f73c..8612e8b 100644
--- a/pym/_emerge/Package.py
+++ b/pym/_emerge/Package.py
@@ -35,8 +35,8 @@ class Package(Task):
                "category", "counter", "cp", "cpv_split",
                "inherited", "iuse", "mtime",
                "pf", "root", "slot", "sub_slot", "slot_atom", "version") + \
-               ("_invalid", "_masks", "_metadata", "_raw_metadata", "_use",
-               "_validated_atoms", "_visible")
+               ("_invalid", "_masks", "_metadata", "_provided_cps",
+               "_raw_metadata", "_use", "_validated_atoms", "_visible")
 
        metadata_keys = [
                "BUILD_TIME", "CHOST", "COUNTER", "DEPEND", "EAPI",
@@ -128,6 +128,20 @@ class Package(Task):
                return self._metadata.properties
 
        @property
+       def provided_cps(self):
+
+               if self._provided_cps is None:
+                       provided_cps = [self.cp]
+                       for atom in self._metadata["PROVIDE"].split():
+                               try:
+                                       provided_cps.append(Atom(atom).cp)
+                               except InvalidAtom:
+                                       pass
+                       self._provided_cps = tuple(provided_cps)
+
+               return self._provided_cps
+
+       @property
        def restrict(self):
                return self._metadata.restrict
 

diff --git a/pym/_emerge/depgraph.py b/pym/_emerge/depgraph.py
index 873c67d..a0169ff 100644
--- a/pym/_emerge/depgraph.py
+++ b/pym/_emerge/depgraph.py
@@ -399,6 +399,7 @@ class _dynamic_depgraph_config(object):
                self._initially_unsatisfied_deps = []
                self._ignored_deps = []
                self._highest_pkg_cache = {}
+               self._highest_pkg_cache_cp_map = {}
                self._flatten_atoms_cache = {}
 
                # Binary packages that have been rejected because their USE
@@ -2539,8 +2540,8 @@ class depgraph(object):
                        if not previously_added:
                                
self._dynamic_config._package_tracker.add_pkg(pkg)
                                
self._dynamic_config._filtered_trees[pkg.root]["porttree"].dbapi._clear_cache()
-                               self._dynamic_config._highest_pkg_cache.clear()
                                self._check_masks(pkg)
+                               self._prune_highest_pkg_cache(pkg)
 
                        if not pkg.installed:
                                # Allow this package to satisfy old-style 
virtuals in case it
@@ -2685,6 +2686,7 @@ class depgraph(object):
                # Clear caches.
                
self._dynamic_config._filtered_trees[pkg.root]["porttree"].dbapi._clear_cache()
                self._dynamic_config._highest_pkg_cache.clear()
+               self._dynamic_config._highest_pkg_cache_cp_map.clear()
 
 
        def _check_masks(self, pkg):
@@ -3981,6 +3983,7 @@ class depgraph(object):
                # Invalidate the package selection cache, since
                # arguments influence package selections.
                self._dynamic_config._highest_pkg_cache.clear()
+               self._dynamic_config._highest_pkg_cache_cp_map.clear()
                for trees in self._dynamic_config._filtered_trees.values():
                        trees["porttree"].dbapi._clear_cache()
 
@@ -5001,6 +5004,8 @@ class depgraph(object):
                        return ret
                ret = self._select_pkg_highest_available_imp(root, atom, 
onlydeps=onlydeps, parent=parent)
                self._dynamic_config._highest_pkg_cache[cache_key] = ret
+               self._dynamic_config._highest_pkg_cache_cp_map. \
+                       setdefault(atom.cp, []).append(cache_key)
                pkg, existing = ret
                if pkg is not None:
                        if self._pkg_visibility_check(pkg) and \
@@ -5014,6 +5019,13 @@ class depgraph(object):
                                return True
                return False
 
+       def _prune_highest_pkg_cache(self, pkg):
+               for cp in pkg.provided_cps:
+                       for cache_key in self._dynamic_config. \
+                               _highest_pkg_cache_cp_map.pop(cp, []):
+                               self._dynamic_config._highest_pkg_cache.pop(
+                                       cache_key, None)
+
        def _want_installed_pkg(self, pkg):
                """
                Given an installed package returned from select_pkg, return

Reply via email to