[PATCH 6 of 7 V6] dirstate: add a C implementation for nonnormalentries

Laurent Charignon lcharignon at fb.com
Mon Dec 21 18:33:15 CST 2015


# HG changeset patch
# User Laurent Charignon <lcharignon at fb.com>
# Date 1450744036 28800
#      Mon Dec 21 16:27:16 2015 -0800
# Node ID cc3b2338b18a45db45a2dcab757455c63e6de0d4
# Parent  ea469e3797c1ea6c20f3b30efe5ef532279dd3ce
dirstate: add a C implementation for nonnormalentries

Before this patch, there was only a python version of nonnormalentries.
On mozilla-central we have a 10x win by putting this function in C:
% python -m timeit -s \
        'from mercurial import hg, ui, parsers; \
        repo = hg.repository(ui.ui(), "mozilla-central"); \
        m = repo.dirstate._map' \
        'parsers.nonnormalentries(m)'

100 loops, best of 3: 3.15 msec per loop

The python implementation runs in 31ms, a similar test gives:
10 loops, best of 3: 31.7 msec per loop

On our big repos, the win is still of 10x with the python implementation running
in 350ms and the C implementation running in 30ms.

diff --git a/mercurial/parsers.c b/mercurial/parsers.c
--- a/mercurial/parsers.c
+++ b/mercurial/parsers.c
@@ -547,6 +547,44 @@ quit:
 }
 
 /*
+ * Build a set of non-normal entries from the dirstate dmap
+*/
+static PyObject *nonnormalentries(PyObject *self, PyObject *args)
+{
+	PyObject *dmap, *nonnset = NULL, *fname, *v;
+	Py_ssize_t pos;
+
+	if (!PyArg_ParseTuple(args, "O!:nonnormalentries",
+			      &PyDict_Type, &dmap))
+		goto bail;
+
+	nonnset = PySet_New(NULL);
+	if (nonnset == NULL)
+		goto bail;
+
+	pos = 0;
+	while (PyDict_Next(dmap, &pos, &fname, &v)) {
+		dirstateTupleObject *t;
+		if (!dirstate_tuple_check(v)) {
+			PyErr_SetString(PyExc_TypeError,
+					"expected a dirstate tuple");
+			goto bail;
+		}
+		t = (dirstateTupleObject *)v;
+
+		if (t->state == 'n' && t->mtime != -1)
+			continue;
+		if (PySet_Add(nonnset, fname) == -1)
+			goto bail;
+	}
+
+	return nonnset;
+bail:
+	Py_XDECREF(nonnset);
+	return NULL;
+}
+
+/*
  * Efficiently pack a dirstate object into its on-disk format.
  */
 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
@@ -2740,6 +2778,8 @@ PyObject *lowerencode(PyObject *self, Py
 
 static PyMethodDef methods[] = {
 	{"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
+	{"nonnormalentries", nonnormalentries, METH_VARARGS,
+	"create a set containing non-normal entries of given dirstate\n"},
 	{"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
 	{"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
 	{"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},


More information about the Mercurial-devel mailing list