Patchwork [07,of,10,V2] revlog: use the native implementation of issnapshot

login
register
mail settings
Submitter Boris Feld
Date Dec. 21, 2018, 11:47 a.m.
Message ID <4b515705427c5ce7f4d5.1545392830@localhost.localdomain>
Download mbox | patch
Permalink /patch/37299/
State Accepted
Headers show

Comments

Boris Feld - Dec. 21, 2018, 11:47 a.m.
# HG changeset patch
# User Boris Feld <boris.feld@octobus.net>
# Date 1545366458 -3600
#      Fri Dec 21 05:27:38 2018 +0100
# Node ID 4b515705427c5ce7f4d55611738ab7f62662dc6b
# Parent  d15f3f46ca1e52f06d5b8f3f77c5e2e02912aaa9
# EXP-Topic sparse-revlog
# Available At https://bitbucket.org/octobus/mercurial-devel/
#              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 4b515705427c
revlog: use the native implementation of issnapshot

In some sparserevlog case where a lot of the history has to be searched for a
snapshot, the cost of issnashot cost becomes significant. The computation done
by the method is fairly low level, a native implementation provide a very
significant speedup.

example affected manifest write
before: 0.490375s
after:  0.114989s (-76%)
Yuya Nishihara - Dec. 22, 2018, 4:11 a.m.
On Fri, 21 Dec 2018 12:47:10 +0100, Boris Feld wrote:
> # HG changeset patch
> # User Boris Feld <boris.feld@octobus.net>
> # Date 1545366458 -3600
> #      Fri Dec 21 05:27:38 2018 +0100
> # Node ID 4b515705427c5ce7f4d55611738ab7f62662dc6b
> # Parent  d15f3f46ca1e52f06d5b8f3f77c5e2e02912aaa9
> # EXP-Topic sparse-revlog
> # Available At https://bitbucket.org/octobus/mercurial-devel/
> #              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 4b515705427c
> revlog: use the native implementation of issnapshot

> +static PyObject *index_issnapshot(indexObject *self, PyObject *value)
> +{
> +	long rev;
> +	int issnap;
> +
> +	if (!pylong_to_long(value, &rev)) {
> +		return NULL;

It should validate the range of the input rev.
Boris Feld - Dec. 27, 2018, 11:28 p.m.
On 22/12/2018 05:11, Yuya Nishihara wrote:
> On Fri, 21 Dec 2018 12:47:10 +0100, Boris Feld wrote:
>> # HG changeset patch
>> # User Boris Feld <boris.feld@octobus.net>
>> # Date 1545366458 -3600
>> #      Fri Dec 21 05:27:38 2018 +0100
>> # Node ID 4b515705427c5ce7f4d55611738ab7f62662dc6b
>> # Parent  d15f3f46ca1e52f06d5b8f3f77c5e2e02912aaa9
>> # EXP-Topic sparse-revlog
>> # Available At https://bitbucket.org/octobus/mercurial-devel/
>> #              hg pull https://bitbucket.org/octobus/mercurial-devel/ -r 4b515705427c
>> revlog: use the native implementation of issnapshot
>> +static PyObject *index_issnapshot(indexObject *self, PyObject *value)
>> +{
>> +	long rev;
>> +	int issnap;
>> +
>> +	if (!pylong_to_long(value, &rev)) {
>> +		return NULL;
> It should validate the range of the input rev.
Good catch, thanks.
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel@mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Patch

diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c
--- a/mercurial/cext/revlog.c
+++ b/mercurial/cext/revlog.c
@@ -1014,6 +1014,21 @@  static int index_issnapshotrev(indexObje
 	return index_issnapshotrev(self, base);
 }
 
+static PyObject *index_issnapshot(indexObject *self, PyObject *value)
+{
+	long rev;
+	int issnap;
+
+	if (!pylong_to_long(value, &rev)) {
+		return NULL;
+	}
+	issnap = index_issnapshotrev(self, (Py_ssize_t)rev);
+	if (issnap < 0) {
+		return NULL;
+	};
+	return PyBool_FromLong((long)issnap);
+}
+
 static PyObject *index_deltachain(indexObject *self, PyObject *args)
 {
 	int rev, generaldelta;
@@ -2626,6 +2641,8 @@  static PyMethodDef index_methods[] = {
      "get head revisions"}, /* Can do filtering since 3.2 */
     {"headrevsfiltered", (PyCFunction)index_headrevs, METH_VARARGS,
      "get filtered head revisions"}, /* Can always do filtering */
+    {"issnapshot", (PyCFunction)index_issnapshot, METH_O,
+     "True if the object is a snapshot"},
     {"deltachain", (PyCFunction)index_deltachain, METH_VARARGS,
      "determine revisions with deltas to reconstruct fulltext"},
     {"slicechunktodensity", (PyCFunction)index_slicechunktodensity,
diff --git a/mercurial/revlog.py b/mercurial/revlog.py
--- a/mercurial/revlog.py
+++ b/mercurial/revlog.py
@@ -1533,6 +1533,12 @@  class revlog(object):
     def issnapshot(self, rev):
         """tells whether rev is a snapshot
         """
+        if not self._generaldelta:
+            return self.deltaparent(rev) == nullrev
+        elif util.safehasattr(self.index, 'issnapshot'):
+            # directly assign the method to cache the testing and access
+            self.issnapshot = self.index.issnapshot
+            return self.issnapshot(rev)
         if rev == nullrev:
             return True
         entry = self.index[rev]