# HG changeset patch # User Martin von Zweigbergk # Date 1422368579 18000 # Node ID 26fbf07482b28e32b3c30d432e0f8396ed5b37c5 # Parent 26d6a6a78c1d855e513626190bc80ffc5cadfc87 _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) diff -r 26d6a6a78c1d -r 26fbf07482b2 mercurial/obsolete.py --- 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 # -> (decoder, encoder) formats = {_fm0version: (_fm0readmarkers, _fm0encodeonemarker), diff -r 26d6a6a78c1d -r 26fbf07482b2 mercurial/parsers.c --- 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} };