stablerange: add a new 'firstmerge' cache
This cache store the first merge ancestors of a changesets. This is useful to
avoid iteration over the changelog when building stablerange.
--- a/hgext3rd/evolve/depthcache.py Wed Dec 20 20:17:11 2017 +0100
+++ b/hgext3rd/evolve/depthcache.py Wed Dec 20 20:46:10 2017 +0100
@@ -71,7 +71,7 @@
@localrepo.unfilteredmethod
def destroyed(self):
- if 'obsstore' in vars(self):
+ if 'depthcache' in vars(self):
self.depthcache.clear()
super(depthcacherepo, self).destroyed()
@@ -97,19 +97,13 @@
if repo is None:
return
repo = repo.unfiltered()
- # As pointed in 'obscache.update', we could have the changelog
- # and the obsstore in charge of updating the cache when new
- # items goes it. The tranaction logic would then only be
- # involved for the 'pending' and final writing on disk.
- self.obsstore.obscache.update(repo)
- self.obsstore.obscache.save(repo)
if (repo.ui.configbool('experimental', 'obshashrange',
False)
and repo.ui.configbool('experimental',
'obshashrange.warm-cache',
True)):
- tr.addpostclose('warmcache-depthcache', _warmcache)
+ tr.addpostclose('warmcache-00depthcache', _warmcache)
return tr
repo.__class__ = depthcacherepo
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hgext3rd/evolve/firstmergecache.py Wed Dec 20 20:46:10 2017 +0100
@@ -0,0 +1,165 @@
+from __future__ import absolute_import
+
+import array
+import weakref
+
+from mercurial import (
+ localrepo,
+ node as nodemod,
+ util,
+)
+
+from . import (
+ error,
+ exthelper,
+ genericcaches,
+ utility,
+)
+
+filterparents = utility.filterparents
+
+eh = exthelper.exthelper()
+
+@eh.reposetup
+def setupcache(ui, repo):
+
+ class firstmergecacherepo(repo.__class__):
+
+ @localrepo.unfilteredpropertycache
+ def firstmergecache(self):
+ cache = firstmergecache()
+ cache.update(self)
+ return cache
+
+ @localrepo.unfilteredmethod
+ def destroyed(self):
+ if 'firstmergecach' in vars(self):
+ self.firstmergecache.clear()
+ super(firstmergecacherepo, self).destroyed()
+
+ if util.safehasattr(repo, 'updatecaches'):
+ @localrepo.unfilteredmethod
+ def updatecaches(self, tr=None):
+ if (repo.ui.configbool('experimental', 'obshashrange',
+ False)
+ and repo.ui.configbool('experimental',
+ 'obshashrange.warm-cache',
+ True)):
+ self.firstmergecache.update(repo)
+ self.firstmergecache.save(repo)
+ super(firstmergecacherepo, self).updatecaches(tr)
+
+ else:
+ def transaction(self, *args, **kwargs):
+ tr = super(firstmergecacherepo, self).transaction(*args, **kwargs)
+ reporef = weakref.ref(self)
+
+ def _warmcache(tr):
+ repo = reporef()
+ if repo is None:
+ return
+ repo = repo.unfiltered()
+ self.firstmergecache.update(repo)
+ self.firstmergecache.save(repo)
+
+ if (repo.ui.configbool('experimental', 'obshashrange',
+ False)
+ and repo.ui.configbool('experimental',
+ 'obshashrange.warm-cache',
+ True)):
+ tr.addpostclose('warmcache-01-firstparentcache', _warmcache)
+ return tr
+
+ repo.__class__ = firstmergecacherepo
+
+class firstmergecache(genericcaches.changelogsourcebase):
+
+ _filepath = 'evoext-firstmerge-00'
+ _cachename = 'evo-ext-firstmerge'
+
+ def __init__(self):
+ super(firstmergecache, self).__init__()
+ self._data = array.array('l')
+
+ def get(self, rev):
+ if len(self._data) <= rev:
+ raise error.ProgrammingError('firstmergecache must be warmed before use')
+ return self._data[rev]
+
+ def _updatefrom(self, repo, data):
+ """compute the rev of one revision, assert previous revision has an hot cache
+ """
+ cl = repo.unfiltered().changelog
+ total = len(data)
+
+ def progress(pos, rev):
+ repo.ui.progress('updating firstmerge cache',
+ pos, 'rev %s' % rev, unit='revision', total=total)
+ progress(0, '')
+ for idx, rev in enumerate(data, 1):
+ assert rev == len(self._data), (rev, len(self._data))
+ self._data.append(self._firstmerge(cl, rev))
+ if not (idx % 10000): # progress as a too high performance impact
+ progress(idx, rev)
+ progress(None, '')
+
+ def _firstmerge(self, changelog, rev):
+ cl = changelog
+ ps = filterparents(cl.parentrevs(rev))
+ if not ps:
+ return nodemod.nullrev
+ elif len(ps) == 1:
+ # linear commit case
+ return self.get(ps[0])
+ else:
+ return rev
+
+ # cache internal logic
+
+ def clear(self, reset=False):
+ """invalidate the cache content
+
+ if 'reset' is passed, we detected a strip and the cache will have to be
+ recomputed.
+
+ Subclasses MUST overide this method to actually affect the cache data.
+ """
+ super(firstmergecache, self).clear()
+ self._data = array.array('l')
+
+ # crude version of a cache, to show the kind of information we have to store
+
+ def load(self, repo):
+ """load data from disk"""
+ assert repo.filtername is None
+
+ if util.safehasattr(repo, 'cachevfs'):
+ data = repo.cachevfs.tryread(self._filepath)
+ else:
+ data = repo.vfs.tryread('cache/' + self._filepath)
+ self._data = array.array('l')
+ if not data:
+ self._cachekey = self.emptykey
+ else:
+ headerdata = data[:self._cachekeysize]
+ self._cachekey = self._deserializecachekey(headerdata)
+ self._data.fromstring(data[self._cachekeysize:])
+ self._ondiskkey = self._cachekey
+
+ def save(self, repo):
+ """save the data to disk
+
+ Format is pretty simple, we serialise the cache key and then drop the
+ bytearray.
+ """
+ if self._cachekey is None or self._cachekey == self._ondiskkey:
+ return
+
+ if util.safehasattr(repo, 'cachevfs'):
+ cachefile = repo.cachevfs(self._filepath, 'w', atomictemp=True)
+ else:
+ cachefile = repo.vfs('cache/' + self._filepath, 'w', atomictemp=True)
+ headerdata = self._serializecachekey()
+ cachefile.write(headerdata)
+ cachefile.write(self._data.tostring())
+ cachefile.close()
--- a/hgext3rd/evolve/stablerange.py Wed Dec 20 20:17:11 2017 +0100
+++ b/hgext3rd/evolve/stablerange.py Wed Dec 20 20:46:10 2017 +0100
@@ -25,8 +25,9 @@
from mercurial.i18n import _
from . import (
+ exthelper,
+ firstmergecache,
stablesort,
- exthelper,
utility,
)
@@ -34,6 +35,7 @@
eh = exthelper.exthelper()
eh.merge(stablesort.eh)
+eh.merge(firstmergecache.eh)
# prior to hg-4.2 there are not util.timer
if util.safehasattr(util, 'timer'):
--- a/tests/test-discovery-obshashrange.t Wed Dec 20 20:17:11 2017 +0100
+++ b/tests/test-discovery-obshashrange.t Wed Dec 20 20:46:10 2017 +0100
@@ -38,6 +38,8 @@
* @0000000000000000000000000000000000000000 (*)> strip detected, evo-ext-depthcache cache reset (glob)
* @0000000000000000000000000000000000000000 (*)> updated evo-ext-depthcache in *.???? seconds (8r) (glob)
* @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (8r, 0o) (glob)
+ * @0000000000000000000000000000000000000000 (*)> strip detected, evo-ext-firstmerge cache reset (glob)
+ * @0000000000000000000000000000000000000000 (*)> updated evo-ext-firstmerge in *.???? seconds (8r) (glob)
* @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob)
* @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 1 nodes (glob)
* @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (8r, 0o) (glob)
@@ -161,6 +163,8 @@
* @0000000000000000000000000000000000000000 (*)> updated evo-ext-depthcache in *.???? seconds (5r) (glob)
* @0000000000000000000000000000000000000000 (*)> updated stablerange cache in *.???? seconds (glob)
* @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (5r, 3o) (glob)
+ * @0000000000000000000000000000000000000000 (*)> strip detected, evo-ext-firstmerge cache reset (glob)
+ * @0000000000000000000000000000000000000000 (*)> updated evo-ext-firstmerge in *.???? seconds (5r) (glob)
* @0000000000000000000000000000000000000000 (*)> updated base branch cache in *.???? seconds (glob)
* @0000000000000000000000000000000000000000 (*)> wrote base branch cache with 1 labels and 1 nodes (glob)
* @0000000000000000000000000000000000000000 (*)> updated evo-ext-obscache in *.???? seconds (5r, 3o) (glob)
@@ -243,6 +247,7 @@
* @0000000000000000000000000000000000000000 (*)> updated evo-ext-depthcache in *.???? seconds (1r) (glob)
* @0000000000000000000000000000000000000000 (*)> updated stablerange cache in *.???? seconds (glob)
* @0000000000000000000000000000000000000000 (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 1o) (glob)
+ * @0000000000000000000000000000000000000000 (*)> updated evo-ext-firstmerge in *.???? seconds (1r) (glob)
* @0000000000000000000000000000000000000000 (*)> obscache is out of date, falling back to slower obsstore version (glob)
* @0000000000000000000000000000000000000000 (*)> updated served branch cache in *.???? seconds (glob)
* @0000000000000000000000000000000000000000 (*)> wrote served branch cache with 1 labels and 2 nodes (glob)
@@ -305,6 +310,7 @@
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> commit -m foo (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (1r) (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 0o) (glob)
+ * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-firstmerge in *.???? seconds (1r) (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obscache is out of date, falling back to slower obsstore version (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated served branch cache in *.???? seconds (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> wrote served branch cache with 1 labels and 1 nodes (glob)
@@ -422,6 +428,7 @@
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> obshashcache reset - new markers affect cached ranges (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (2r, 3o) (glob)
+ * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-firstmerge in *.???? seconds (2r) (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated served branch cache in *.???? seconds (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> wrote served branch cache with 1 labels and 2 nodes (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (2r, 3o) (glob)
@@ -568,12 +575,15 @@
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (1r) (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 1o) (glob)
+ * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-firstmerge in *.???? seconds (1r) (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated served branch cache in *.???? seconds (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> wrote served branch cache with 1 labels and 2 nodes (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (1r, 1o) (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> 1 incoming changes - new heads: 4de32a90b66c (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull exited 0 after *.?? seconds (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> rollback (glob)
+ * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-firstmerge cache reset (glob)
+ * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-firstmerge in *.???? seconds (8r) (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> strip detected, evo-ext-depthcache cache reset (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (8r) (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated base branch cache in *.???? seconds (glob)
@@ -623,6 +633,7 @@
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-depthcache in *.???? seconds (1r) (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated stablerange cache in *.???? seconds (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 1o) (glob)
+ * @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-firstmerge in *.???? seconds (1r) (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> updated evo-ext-obscache in *.???? seconds (1r, 1o) (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> 1 incoming changes - new heads: 4de32a90b66c (glob)
* @45f8b879de922f6a6e620ba04205730335b6fc7e (*)> pull exited 0 after *.?? seconds (glob)
@@ -736,11 +747,14 @@
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-depthcache cache reset (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-depthcache in *.???? seconds (5r) (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obshashrange in *.???? seconds (5r, 11o) (glob)
+ * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-firstmerge cache reset (glob)
+ * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-firstmerge in *.???? seconds (5r) (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> strip detected, evo-ext-obscache cache reset (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (5r, 11o) (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-depthcache in *.???? seconds (3r) (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated stablerange cache in *.???? seconds (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obshashrange in *.???? seconds (3r, 0o) (glob)
+ * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-firstmerge in *.???? seconds (3r) (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (3r, 0o) (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated base branch cache in *.???? seconds (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> wrote base branch cache with 1 labels and 1 nodes (glob)
@@ -755,6 +769,7 @@
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated stablerange cache in *.???? seconds (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> obshashcache reset - new markers affect cached ranges (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obshashrange in *.???? seconds (1r, 2o) (glob)
+ * @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-firstmerge in *.???? seconds (1r) (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated base branch cache in *.???? seconds (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> wrote base branch cache with 1 labels and 2 nodes (glob)
* @bebd167eb94d257ace0e814aeb98e6972ed2970d (*)> updated evo-ext-obscache in *.???? seconds (1r, 2o) (glob)