[PATCH 3 of 3 V2] obsolete: populate successors, precursors, children lazily

Martin von Zweigbergk martinvonz at google.com
Thu Feb 5 01:22:54 CST 2015


# HG changeset patch
# User Martin von Zweigbergk <martinvonz at google.com>
# Date 1423117535 28800
#      Wed Feb 04 22:25:35 2015 -0800
# Node ID f39fafaf42399f7a8ca6aab000b023c95029a4ee
# Parent  1465976cb03a60d8e572a1a78c756092528c621a
obsolete: populate successors, precursors, children lazily

The precursors and children dictionaries are not used by many
commands. By making them lazily populated,
'hg log -r @~10::@ >/dev/null' is sped up from 0.564s to 0.440s on my
hg.hg repo with 73k markers.

Also make sucessors lazily populated, mostly for consistency with the
others.

diff -r 1465976cb03a -r f39fafaf4239 mercurial/obsolete.py
--- a/mercurial/obsolete.py	Wed Feb 04 22:40:48 2015 -0800
+++ b/mercurial/obsolete.py	Wed Feb 04 22:25:35 2015 -0800
@@ -75,6 +75,7 @@
 _pack = struct.pack
 _unpack = struct.unpack
 _calcsize = struct.calcsize
+propertycache = util.propertycache
 
 _SEEK_END = 2 # os.SEEK_END was introduced in Python 2.5
 
@@ -522,16 +523,13 @@
         # caches for various obsolescence related cache
         self.caches = {}
         self._all = []
-        self.precursors = {}
-        self.successors = {}
-        self.children = {}
         self.sopener = sopener
         data = sopener.tryread('obsstore')
         self._version = defaultformat
         self._readonly = readonly
         if data:
             self._version, markers = _readmarkers(data)
-            self._load(markers)
+            self._addmarkers(markers)
 
     def __iter__(self):
         return iter(self._all)
@@ -609,7 +607,7 @@
                 # XXX: f.close() == filecache invalidation == obsstore rebuilt.
                 # call 'filecacheentry.refresh()'  here
                 f.close()
-            self._load(new)
+            self._addmarkers(new)
             # new marker *may* have changed several set. invalidate the cache.
             self.caches.clear()
         # records the number of new markers for the transaction hooks
@@ -624,12 +622,36 @@
         version, markers = _readmarkers(data)
         return self.add(transaction, markers)
 
-    def _load(self, markers):
+    @propertycache
+    def successors(self):
+        successors = {}
+        _addsuccessors(successors, self._all)
+        return successors
+
+    @propertycache
+    def precursors(self):
+        precursors = {}
+        _addprecursors(precursors, self._all)
+        return precursors
+
+    @propertycache
+    def children(self):
+        children = {}
+        _addchildren(children, self._all)
+        return children
+
+    def _cached(self, attr):
+        return attr in self.__dict__
+
+    def _addmarkers(self, markers):
         markers = list(markers) # to allow repeated iteration
         self._all.extend(markers)
-        _addsuccessors(self.successors, markers)
-        _addprecursors(self.precursors, markers)
-        _addchildren(self.children, markers)
+        if self._cached('successors'):
+            _addsuccessors(self.successors, markers)
+        if self._cached('precursors'):
+            _addprecursors(self.precursors, markers)
+        if self._cached('children'):
+            _addchildren(self.children, markers)
         _checkinvalidmarkers(markers)
 
     def relevantmarkers(self, nodes):


More information about the Mercurial-devel mailing list