Mercurial > hg
comparison mercurial/parsers.c @ 16786:2631cd5dd244
revlog: switch to a C version of headrevs
The C implementation is more than 100 times faster than the Python
version (which is still available as a fallback).
In a repo with 330,000 revs and a stale .hg/cache/tags file, this
patch improves the performance of "hg tip" from 2.2 to 1.6 seconds.
author | Bryan O'Sullivan <bryano@fb.com> |
---|---|
date | Sat, 19 May 2012 19:44:58 -0700 |
parents | 12a852c7c763 |
children | bda96ce993f9 |
comparison
equal
deleted
inserted
replaced
16785:1dc08dc63c09 | 16786:2631cd5dd244 |
---|---|
532 bail: | 532 bail: |
533 Py_XDECREF(obj); | 533 Py_XDECREF(obj); |
534 return NULL; | 534 return NULL; |
535 } | 535 } |
536 | 536 |
537 static PyObject *index_headrevs(indexObject *self) | |
538 { | |
539 Py_ssize_t i, len, addlen; | |
540 char *nothead = NULL; | |
541 PyObject *heads; | |
542 | |
543 len = index_length(self) - 1; | |
544 heads = PyList_New(0); | |
545 if (heads == NULL) | |
546 goto bail; | |
547 if (len == 0) { | |
548 PyObject *nullid = PyInt_FromLong(-1); | |
549 if (nullid == NULL || PyList_Append(heads, nullid) == -1) { | |
550 Py_XDECREF(nullid); | |
551 goto bail; | |
552 } | |
553 goto done; | |
554 } | |
555 | |
556 nothead = calloc(len, 1); | |
557 if (nothead == NULL) | |
558 goto bail; | |
559 | |
560 for (i = 0; i < self->raw_length; i++) { | |
561 const char *data = index_deref(self, i); | |
562 int parent_1 = getbe32(data + 24); | |
563 int parent_2 = getbe32(data + 28); | |
564 if (parent_1 >= 0) | |
565 nothead[parent_1] = 1; | |
566 if (parent_2 >= 0) | |
567 nothead[parent_2] = 1; | |
568 } | |
569 | |
570 addlen = self->added ? PyList_GET_SIZE(self->added) : 0; | |
571 | |
572 for (i = 0; i < addlen; i++) { | |
573 PyObject *rev = PyList_GET_ITEM(self->added, i); | |
574 PyObject *p1 = PyTuple_GET_ITEM(rev, 5); | |
575 PyObject *p2 = PyTuple_GET_ITEM(rev, 6); | |
576 long parent_1, parent_2; | |
577 | |
578 if (!PyInt_Check(p1) || !PyInt_Check(p2)) { | |
579 PyErr_SetString(PyExc_TypeError, | |
580 "revlog parents are invalid"); | |
581 goto bail; | |
582 } | |
583 parent_1 = PyInt_AS_LONG(p1); | |
584 parent_2 = PyInt_AS_LONG(p2); | |
585 if (parent_1 >= 0) | |
586 nothead[parent_1] = 1; | |
587 if (parent_2 >= 0) | |
588 nothead[parent_2] = 1; | |
589 } | |
590 | |
591 for (i = 0; i < len; i++) { | |
592 PyObject *head; | |
593 | |
594 if (nothead[i]) | |
595 continue; | |
596 head = PyInt_FromLong(i); | |
597 if (head == NULL || PyList_Append(heads, head) == -1) { | |
598 Py_XDECREF(head); | |
599 goto bail; | |
600 } | |
601 } | |
602 | |
603 done: | |
604 free(nothead); | |
605 return heads; | |
606 bail: | |
607 Py_XDECREF(heads); | |
608 free(nothead); | |
609 return NULL; | |
610 } | |
611 | |
537 static inline int nt_level(const char *node, Py_ssize_t level) | 612 static inline int nt_level(const char *node, Py_ssize_t level) |
538 { | 613 { |
539 int v = node[level>>1]; | 614 int v = node[level>>1]; |
540 if (!(level & 1)) | 615 if (!(level & 1)) |
541 v >>= 4; | 616 v >>= 4; |
1142 static PyMethodDef index_methods[] = { | 1217 static PyMethodDef index_methods[] = { |
1143 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS, | 1218 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS, |
1144 "clear the index caches"}, | 1219 "clear the index caches"}, |
1145 {"get", (PyCFunction)index_m_get, METH_VARARGS, | 1220 {"get", (PyCFunction)index_m_get, METH_VARARGS, |
1146 "get an index entry"}, | 1221 "get an index entry"}, |
1222 {"headrevs", (PyCFunction)index_headrevs, METH_NOARGS, | |
1223 "get head revisions"}, | |
1147 {"insert", (PyCFunction)index_insert, METH_VARARGS, | 1224 {"insert", (PyCFunction)index_insert, METH_VARARGS, |
1148 "insert an index entry"}, | 1225 "insert an index entry"}, |
1149 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS, | 1226 {"partialmatch", (PyCFunction)index_partialmatch, METH_VARARGS, |
1150 "match a potentially ambiguous node ID"}, | 1227 "match a potentially ambiguous node ID"}, |
1151 {"stats", (PyCFunction)index_stats, METH_NOARGS, | 1228 {"stats", (PyCFunction)index_stats, METH_NOARGS, |