_fm1readmarkers: generate list in C
authorMartin von Zweigbergk <martinvonz@google.com>
Tue, 27 Jan 2015 09:22:59 -0500
changeset 24019 26fbf07482b2
parent 24018 26d6a6a78c1d
child 24020 cc81e6da0757
_fm1readmarkers: generate list in C This moves perfloadmarkers from ! result: 63866 ! wall 0.239217 comb 0.250000 user 0.240000 sys 0.010000 (best of 42) to ! result: 63866 ! wall 0.218795 comb 0.210000 user 0.210000 sys 0.000000 (best of 46)
mercurial/obsolete.py
mercurial/parsers.c
--- a/mercurial/obsolete.py	Tue Jan 20 13:38:07 2015 -0500
+++ b/mercurial/obsolete.py	Tue Jan 27 09:22:59 2015 -0500
@@ -285,7 +285,7 @@
 _fm1metapair = 'BB'
 _fm1metapairsize = _calcsize('BB')
 
-def _fm1readmarkers(data, off):
+def _fm1purereadmarkers(data, off):
     # make some global constants local for performance
     noneflag = _fm1parentnone
     sha2flag = usingsha256
@@ -302,14 +302,6 @@
     stop = len(data) - _fm1fsize
     ufixed = util.unpacker(_fm1fixed)
 
-    fast = getattr(parsers, 'fm1readmarker', None)
-    if fast is not None:
-        while off <= stop:
-            ret = fast(data, off)
-            yield ret[1:]
-            off += ret[0]
-        return
-
     while off <= stop:
         # read fixed part
         o1 = off + fsize
@@ -404,6 +396,13 @@
         data.append(value)
     return ''.join(data)
 
+def _fm1readmarkers(data, off):
+    native = getattr(parsers, 'fm1readmarkers', None)
+    if not native:
+        return _fm1purereadmarkers(data, off)
+    stop = len(data) - _fm1fsize
+    return native(data, off, stop)
+
 # mapping to read/write various marker formats
 # <version> -> (decoder, encoder)
 formats = {_fm0version: (_fm0readmarkers, _fm0encodeonemarker),
--- a/mercurial/parsers.c	Tue Jan 20 13:38:07 2015 -0500
+++ b/mercurial/parsers.c	Tue Jan 27 09:22:59 2015 -0500
@@ -2169,13 +2169,10 @@
 	return list;
 }
 
-static PyObject *fm1readmarker(PyObject *self, PyObject *args)
+static PyObject *fm1readmarker(const char *data, uint32_t *msize)
 {
-	const char *data;
 	const char *meta;
-	Py_ssize_t datalen, offset;
 
-	uint32_t msize;
 	double mtime;
 	int16_t tz;
 	uint16_t flags;
@@ -2186,12 +2183,7 @@
 	PyObject *metadata = NULL, *ret = NULL;
 	int i;
 
-	if (!PyArg_ParseTuple(args, "s#n", &data, &datalen, &offset)) {
-		return NULL;
-	}
-	data += offset;
-
-	msize = getbe32(data);
+	*msize = getbe32(data);
 	data += 4;
 	mtime = getbefloat64(data);
 	data += 8;
@@ -2256,7 +2248,7 @@
 		}
 		PyTuple_SetItem(metadata, i, tmp);
 	}
-	ret = Py_BuildValue("(nOOHO(di)O)", msize, prec, succs, flags,
+	ret = Py_BuildValue("(OOHO(di)O)", prec, succs, flags,
 			    metadata, mtime, (int)tz * 60, parents);
 bail:
 	Py_XDECREF(prec);
@@ -2267,6 +2259,41 @@
 	return ret;
 }
 
+
+static PyObject *fm1readmarkers(PyObject *self, PyObject *args) {
+	const char *data;
+	Py_ssize_t datalen, offset, stop;
+	PyObject *markers = NULL;
+
+	if (!PyArg_ParseTuple(args, "s#nn", &data, &datalen, &offset, &stop)) {
+		return NULL;
+	}
+	data += offset;
+	markers = PyList_New(0);
+	if (!markers) {
+		return NULL;
+	}
+	while (offset < stop) {
+		uint32_t msize;
+		int error;
+		PyObject *record = fm1readmarker(data, &msize);
+		if (!record) {
+			goto bail;
+		}
+		error = PyList_Append(markers, record);
+		Py_DECREF(record);
+		if (error) {
+			goto bail;
+		}
+		data += msize;
+		offset += msize;
+	}
+	return markers;
+bail:
+	Py_DECREF(markers);
+	return NULL;
+}
+
 static char parsers_doc[] = "Efficient content parsing.";
 
 PyObject *encodedir(PyObject *self, PyObject *args);
@@ -2282,7 +2309,8 @@
 	{"encodedir", encodedir, METH_VARARGS, "encodedir a path\n"},
 	{"pathencode", pathencode, METH_VARARGS, "fncache-encode a path\n"},
 	{"lowerencode", lowerencode, METH_VARARGS, "lower-encode a path\n"},
-	{"fm1readmarker", fm1readmarker, METH_VARARGS, "parse v1 obsolete marker\n"},
+	{"fm1readmarkers", fm1readmarkers, METH_VARARGS,
+			"parse v1 obsolete markers\n"},
 	{NULL, NULL}
 };