reachableroots: use internal "revstates" array to test if rev is reachable
authorYuya Nishihara <yuya@tcha.org>
Fri, 14 Aug 2015 15:49:11 +0900
changeset 26054 5049e10fed14
parent 26053 b68c9d232db6
child 26055 607868eccaa7
reachableroots: use internal "revstates" array to test if rev is reachable This is faster than using PySet_Contains(). revset #0: 0::tip 1) 0.003678 2) 0.002536 68%
mercurial/parsers.c
--- a/mercurial/parsers.c	Fri Aug 14 15:43:29 2015 +0900
+++ b/mercurial/parsers.c	Fri Aug 14 15:49:11 2015 +0900
@@ -1135,7 +1135,7 @@
 	 * revstates: array of length len+1 (all revs + nullrev) */
 	int *tovisit = NULL;
 	long lentovisit = 0;
-	enum { RS_SEEN = 1, RS_ROOT = 2 };
+	enum { RS_SEEN = 1, RS_ROOT = 2, RS_REACHABLE = 4 };
 	char *revstates = NULL;
 
 	/* Get arguments */
@@ -1201,6 +1201,7 @@
 		/* Add the node to reachable if it is a root*/
 		revnum = tovisit[k++];
 		if (revstates[revnum + 1] & RS_ROOT) {
+			revstates[revnum + 1] |= RS_REACHABLE;
 			val = PyInt_FromLong(revnum);
 			if (val == NULL)
 				goto bail;
@@ -1240,17 +1241,14 @@
 			if (r < 0)
 				goto bail;
 			for (k = 0; k < 2; k++) {
-				PyObject *p = PyInt_FromLong(parents[k]);
-				if (p == NULL)
-					goto bail;
-				if (PySet_Contains(reachable, p) == 1) {
+				if (revstates[parents[k] + 1] & RS_REACHABLE) {
+					revstates[i + 1] |= RS_REACHABLE;
 					val = PyInt_FromLong(i);
 					if (val == NULL)
 						goto bail;
 					PySet_Add(reachable, val);
 					Py_DECREF(val);
 				}
-				Py_DECREF(p);
 			}
 		}
 	}