comparison mercurial/parsers.c @ 27592:7c9eb2927879

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.
author Laurent Charignon <lcharignon@fb.com>
date Mon, 21 Dec 2015 16:27:16 -0800
parents 41127e875758
children 90e3c5129226
comparison
equal deleted inserted replaced
27591:127cc7f78475 27592:7c9eb2927879
545 Py_XDECREF(parents); 545 Py_XDECREF(parents);
546 return ret; 546 return ret;
547 } 547 }
548 548
549 /* 549 /*
550 * Build a set of non-normal entries from the dirstate dmap
551 */
552 static PyObject *nonnormalentries(PyObject *self, PyObject *args)
553 {
554 PyObject *dmap, *nonnset = NULL, *fname, *v;
555 Py_ssize_t pos;
556
557 if (!PyArg_ParseTuple(args, "O!:nonnormalentries",
558 &PyDict_Type, &dmap))
559 goto bail;
560
561 nonnset = PySet_New(NULL);
562 if (nonnset == NULL)
563 goto bail;
564
565 pos = 0;
566 while (PyDict_Next(dmap, &pos, &fname, &v)) {
567 dirstateTupleObject *t;
568 if (!dirstate_tuple_check(v)) {
569 PyErr_SetString(PyExc_TypeError,
570 "expected a dirstate tuple");
571 goto bail;
572 }
573 t = (dirstateTupleObject *)v;
574
575 if (t->state == 'n' && t->mtime != -1)
576 continue;
577 if (PySet_Add(nonnset, fname) == -1)
578 goto bail;
579 }
580
581 return nonnset;
582 bail:
583 Py_XDECREF(nonnset);
584 return NULL;
585 }
586
587 /*
550 * Efficiently pack a dirstate object into its on-disk format. 588 * Efficiently pack a dirstate object into its on-disk format.
551 */ 589 */
552 static PyObject *pack_dirstate(PyObject *self, PyObject *args) 590 static PyObject *pack_dirstate(PyObject *self, PyObject *args)
553 { 591 {
554 PyObject *packobj = NULL; 592 PyObject *packobj = NULL;
2738 PyObject *pathencode(PyObject *self, PyObject *args); 2776 PyObject *pathencode(PyObject *self, PyObject *args);
2739 PyObject *lowerencode(PyObject *self, PyObject *args); 2777 PyObject *lowerencode(PyObject *self, PyObject *args);
2740 2778
2741 static PyMethodDef methods[] = { 2779 static PyMethodDef methods[] = {
2742 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"}, 2780 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
2781 {"nonnormalentries", nonnormalentries, METH_VARARGS,
2782 "create a set containing non-normal entries of given dirstate\n"},
2743 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, 2783 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
2744 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, 2784 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
2745 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"}, 2785 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
2746 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"}, 2786 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
2747 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"}, 2787 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"},