# HG changeset patch # User Martin von Zweigbergk # Date 1423117535 28800 # Node ID 6e1d9f9932a9960c72172d3c3c1a41ff932f3723 # Parent 43061f96e40edbb841993197223ae6d1b42128a4 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 successors lazily populated, mostly for consistency with the others. diff -r 43061f96e40e -r 6e1d9f9932a9 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):