_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)
--- 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}
};