Create a digraph.difference_update() method and use it to amortize the
authorZac Medico <zmedico@gentoo.org>
Sun, 27 Apr 2008 06:31:11 +0000 (06:31 -0000)
committerZac Medico <zmedico@gentoo.org>
Sun, 27 Apr 2008 06:31:11 +0000 (06:31 -0000)
cost of removing nodes from the digraph.order list.

svn path=/main/trunk/; revision=9992

pym/_emerge/__init__.py
pym/portage/__init__.py

index a73a7423bf15200525dcd0533f040e537e652741..7e8308a9a9d6f2535e191346efd45c938849ef1d 100644 (file)
@@ -3312,16 +3312,18 @@ class depgraph(object):
                # otherwise they slow down merge order calculation. Don't remove
                # non-root nodes since they help optimize merge order in some cases
                # such as revdep-rebuild.
+               removed_nodes = set()
                while True:
-                       removed_something = False
                        for node in mygraph.root_nodes():
                                if not isinstance(node, Package) or \
                                        node.installed or node.onlydeps:
-                                       self.spinner.update()
-                                       mygraph.remove(node)
-                                       removed_something = True
-                       if not removed_something:
+                                       removed_nodes.add(node)
+                       if removed_nodes:
+                               self.spinner.update()
+                               mygraph.difference_update(removed_nodes)
+                       if not removed_nodes:
                                break
+                       removed_nodes.clear()
                self._merge_order_bias(mygraph)
                def cmp_circular_bias(n1, n2):
                        """
@@ -3671,6 +3673,8 @@ class depgraph(object):
                        prefer_asap = True
                        accept_root_node = False
 
+                       mygraph.difference_update(selected_nodes)
+
                        for node in selected_nodes:
 
                                # Handle interactions between blockers
@@ -3706,7 +3710,7 @@ class depgraph(object):
 
                                if node[-1] != "nomerge":
                                        retlist.append(node)
-                               mygraph.remove(node)
+
                                if isinstance(node, Uninstall):
                                        # Include satisfied blockers in the merge list so
                                        # that the user can see why the package had to be
index bd32623a06259be7b9cf84ac8689121d84929cbb..1a75bac160b4e4ec626823df7be84d7caa12ee7d 100644 (file)
@@ -389,6 +389,26 @@ class digraph(object):
                del self.nodes[node]
                self.order.remove(node)
 
+       def difference_update(self, t):
+               """
+               Remove all given nodes from node_set. This is more efficient
+               than multiple calls to the remove() method.
+               """
+               if isinstance(t, (list, tuple)) or \
+                       not hasattr(t, "__contains__"):
+                       t = frozenset(t)
+               order = []
+               for node in self.order:
+                       if node not in t:
+                               order.append(node)
+                               continue
+                       for parent in self.nodes[node][1]:
+                               del self.nodes[parent][0][node]
+                       for child in self.nodes[node][0]:
+                               del self.nodes[child][1][node]
+                       del self.nodes[node]
+               self.order = order
+
        def remove_edge(self, child, parent):
                """
                Remove edge in the direction from child to parent. Note that it is