comparison mercurial/parsers.c @ 31278:1c97a91a18dc

dirstate: track otherparent files same as nonnormal Calling dirstate.setparents() is expensive in a large repo because it iterates over every file in the dirstate. It does so to undo any merge state or otherparent state files. Merge state files are already covered by dirstate._nonnormalset, so we just need to track otherparent files in a similar manner to avoid the full iteration here. Fixing this shaves 20-25% off histedit in large repos. I tested this by adding temporary debug logic to verify that the old files processed in the loop matched the new files processed in the loop and running the test suite.
author Durham Goode <durham@fb.com>
date Wed, 08 Mar 2017 17:35:20 -0800
parents 6146d5acee69
children fffd1abb1337
comparison
equal deleted inserted replaced
31276:cd29673cebdb 31278:1c97a91a18dc
558 Py_XDECREF(parents); 558 Py_XDECREF(parents);
559 return ret; 559 return ret;
560 } 560 }
561 561
562 /* 562 /*
563 * Build a set of non-normal entries from the dirstate dmap 563 * Build a set of non-normal and other parent entries from the dirstate dmap
564 */ 564 */
565 static PyObject *nonnormalentries(PyObject *self, PyObject *args) 565 static PyObject *nonnormalotherparententries(PyObject *self, PyObject *args) {
566 { 566 PyObject *dmap, *fname, *v;
567 PyObject *dmap, *nonnset = NULL, *fname, *v; 567 PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL;
568 Py_ssize_t pos; 568 Py_ssize_t pos;
569 569
570 if (!PyArg_ParseTuple(args, "O!:nonnormalentries", 570 if (!PyArg_ParseTuple(args, "O!:nonnormalentries",
571 &PyDict_Type, &dmap)) 571 &PyDict_Type, &dmap))
572 goto bail; 572 goto bail;
573 573
574 nonnset = PySet_New(NULL); 574 nonnset = PySet_New(NULL);
575 if (nonnset == NULL) 575 if (nonnset == NULL)
576 goto bail;
577
578 otherpset = PySet_New(NULL);
579 if (otherpset == NULL)
576 goto bail; 580 goto bail;
577 581
578 pos = 0; 582 pos = 0;
579 while (PyDict_Next(dmap, &pos, &fname, &v)) { 583 while (PyDict_Next(dmap, &pos, &fname, &v)) {
580 dirstateTupleObject *t; 584 dirstateTupleObject *t;
583 "expected a dirstate tuple"); 587 "expected a dirstate tuple");
584 goto bail; 588 goto bail;
585 } 589 }
586 t = (dirstateTupleObject *)v; 590 t = (dirstateTupleObject *)v;
587 591
592 if (t->state == 'n' && t->size == -2) {
593 if (PySet_Add(otherpset, fname) == -1) {
594 goto bail;
595 }
596 }
597
588 if (t->state == 'n' && t->mtime != -1) 598 if (t->state == 'n' && t->mtime != -1)
589 continue; 599 continue;
590 if (PySet_Add(nonnset, fname) == -1) 600 if (PySet_Add(nonnset, fname) == -1)
591 goto bail; 601 goto bail;
592 } 602 }
593 603
594 return nonnset; 604 result = Py_BuildValue("(OO)", nonnset, otherpset);
605 if (result == NULL)
606 goto bail;
607 return result;
595 bail: 608 bail:
596 Py_XDECREF(nonnset); 609 Py_XDECREF(nonnset);
610 Py_XDECREF(otherpset);
611 Py_XDECREF(result);
597 return NULL; 612 return NULL;
613 }
614
615 /*
616 * Build a set of non-normal entries from the dirstate dmap
617 */
618 static PyObject *nonnormalentries(PyObject *self, PyObject *args)
619 {
620 PyObject *nonnset = NULL, *combined = NULL;
621
622 combined = nonnormalotherparententries(self, args);
623 if (!combined) {
624 return NULL;
625 }
626
627 nonnset = PyTuple_GetItem(combined, 0);
628 if (!nonnset) {
629 Py_DECREF(combined);
630 return NULL;
631 }
632
633 Py_INCREF(nonnset);
634 Py_DECREF(combined);
635 return nonnset;
598 } 636 }
599 637
600 /* 638 /*
601 * Efficiently pack a dirstate object into its on-disk format. 639 * Efficiently pack a dirstate object into its on-disk format.
602 */ 640 */
2814 2852
2815 static PyMethodDef methods[] = { 2853 static PyMethodDef methods[] = {
2816 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"}, 2854 {"pack_dirstate", pack_dirstate, METH_VARARGS, "pack a dirstate\n"},
2817 {"nonnormalentries", nonnormalentries, METH_VARARGS, 2855 {"nonnormalentries", nonnormalentries, METH_VARARGS,
2818 "create a set containing non-normal entries of given dirstate\n"}, 2856 "create a set containing non-normal entries of given dirstate\n"},
2857 {"nonnormalotherparententries", nonnormalotherparententries, METH_VARARGS,
2858 "create a set containing non-normal and other parent entries of given "
2859 "dirstate\n"},
2819 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"}, 2860 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
2820 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"}, 2861 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
2821 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"}, 2862 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
2822 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"}, 2863 {"asciilower", asciilower, METH_VARARGS, "lowercase an ASCII string\n"},
2823 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"}, 2864 {"asciiupper", asciiupper, METH_VARARGS, "uppercase an ASCII string\n"},