[PATCH 11 of 22] obsstore: generalize successors, precursors, children to a class
Jun Wu
quark at fb.com
Sun Jun 4 19:59:23 EDT 2017
# HG changeset patch
# User Jun Wu <quark at fb.com>
# Date 1496558287 25200
# Sat Jun 03 23:38:07 2017 -0700
# Node ID 69870e8f6bc97775c47d363efc5c58bce33239c0
# Parent 994e09024cdd5bbca80f1beb9dcbd2f1a19aa1bb
# Available At https://bitbucket.org/quark-zju/hg-draft
# hg pull https://bitbucket.org/quark-zju/hg-draft -r 69870e8f6bc9
obsstore: generalize successors, precursors, children to a class
Add a "markerindex" class which takes a function to extract key from a
marker. Therefore "successors", "precursors", "children" can reuse the same
implementation by specifying different "keyfunc"s.
There is no noticeable perf change running "hg log -r ." in hg-committed.
I guess subclassing builtin dict is the key to gain good perf. Note the
"dict" base class is temporary and will be changed in a later patch.
diff --git a/mercurial/obsolete.py b/mercurial/obsolete.py
--- a/mercurial/obsolete.py
+++ b/mercurial/obsolete.py
@@ -72,4 +72,5 @@ from __future__ import absolute_import
import errno
import struct
+import weakref
from .i18n import _
@@ -507,22 +508,26 @@ class marker(object):
return self._data[2]
- at util.nogc
-def _addsuccessors(successors, markers):
- for mark in markers:
- successors.setdefault(mark[0], set()).add(mark)
+class markerindex(dict):
+ """key is usually a node, value is a set of markers"""
+
+ def __init__(self, obsstore, name, keyfunc):
+ """keyfunc: rawmarker -> [key]"""
+ self._keyfunc = keyfunc
+ self._obsstore = weakref.proxy(obsstore)
+ self.name = name
+ self.sourceoftruthsize = 0
+ self.update()
- at util.nogc
-def _addprecursors(precursors, markers):
- for mark in markers:
- for suc in mark[1]:
- precursors.setdefault(suc, set()).add(mark)
-
- at util.nogc
-def _addchildren(children, markers):
- for mark in markers:
- parents = mark[5]
- if parents is not None:
- for p in parents:
- children.setdefault(p, set()).add(mark)
+ @util.nogc
+ def update(self):
+ """read latest obsstore and build index for its markers"""
+ allmarkers = self._obsstore._all
+ keyfunc = self._keyfunc
+ setdefault = self.setdefault
+ for i in xrange(self.sourceoftruthsize, len(allmarkers)):
+ marker = allmarkers[i]
+ for k in keyfunc(marker):
+ setdefault(k, set()).add(marker)
+ self.sourceoftruthsize = len(allmarkers)
def _checkinvalidmarkers(markers):
@@ -693,19 +698,13 @@ class obsstore(object):
@propertycache
def successors(self):
- successors = {}
- _addsuccessors(successors, self._all)
- return successors
+ return markerindex(self, 'successors', lambda m: (m[0],))
@propertycache
def precursors(self):
- precursors = {}
- _addprecursors(precursors, self._all)
- return precursors
+ return markerindex(self, 'precursors', lambda m: m[1])
@propertycache
def children(self):
- children = {}
- _addchildren(children, self._all)
- return children
+ return markerindex(self, 'children', lambda m: m[5] or ())
def _cached(self, attr):
@@ -716,10 +715,8 @@ class obsstore(object):
self._data = self._data + rawdata
self._all.extend(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)
+ for name in ('successors', 'precursors', 'children'):
+ index = self.__dict__.get(name, None)
+ if index is not None:
+ index.update()
_checkinvalidmarkers(markers)
More information about the Mercurial-devel
mailing list