comparison mercurial/dirs.c @ 21809:e250b8300e6e

parsers: inline fields of dirstate values in C version Previously, while unpacking the dirstate we'd create 3-4 new CPython objects for most dirstate values: - the state is a single character string, which is pooled by CPython - the mode is a new object if it isn't 0 due to being in the lookup set - the size is a new object if it is greater than 255 - the mtime is a new object if it isn't -1 due to being in the lookup set - the tuple to contain them all In some cases such as regular hg status, we actually look at all the objects. In other cases like hg add, hg status for a subdirectory, or hg status with the third-party hgwatchman enabled, we look at almost none of the objects. This patch eliminates most object creation in these cases by defining a custom C struct that is exposed to Python with an interface similar to a tuple. Only when tuple elements are actually requested are the respective objects created. The gains, where they're expected, are significant. The following tests are run against a working copy with over 270,000 files. parse_dirstate becomes significantly faster: $ hg perfdirstate before: wall 0.186437 comb 0.180000 user 0.160000 sys 0.020000 (best of 35) after: wall 0.093158 comb 0.100000 user 0.090000 sys 0.010000 (best of 95) and as a result, several commands benefit: $ time hg status # with hgwatchman enabled before: 0.42s user 0.14s system 99% cpu 0.563 total after: 0.34s user 0.12s system 99% cpu 0.471 total $ time hg add new-file before: 0.85s user 0.18s system 99% cpu 1.033 total after: 0.76s user 0.17s system 99% cpu 0.931 total There is a slight regression in regular status performance, but this is fixed in an upcoming patch.
author Siddharth Agarwal <sid0@fb.com>
date Tue, 27 May 2014 14:27:41 -0700
parents 8c0a7eeda06d
children bca4b6f126f2
comparison
equal deleted inserted replaced
21808:7537e57f5dbd 21809:e250b8300e6e
136 if (!PyString_Check(key)) { 136 if (!PyString_Check(key)) {
137 PyErr_SetString(PyExc_TypeError, "expected string key"); 137 PyErr_SetString(PyExc_TypeError, "expected string key");
138 return -1; 138 return -1;
139 } 139 }
140 if (skipchar) { 140 if (skipchar) {
141 PyObject *st; 141 if (!dirstate_tuple_check(value)) {
142
143 if (!PyTuple_Check(value) ||
144 PyTuple_GET_SIZE(value) == 0) {
145 PyErr_SetString(PyExc_TypeError, 142 PyErr_SetString(PyExc_TypeError,
146 "expected non-empty tuple"); 143 "expected a dirstate tuple");
147 return -1; 144 return -1;
148 } 145 }
149 146 if (((dirstateTupleObject *)value)->state == skipchar)
150 st = PyTuple_GET_ITEM(value, 0);
151
152 if (!PyString_Check(st) || PyString_GET_SIZE(st) == 0) {
153 PyErr_SetString(PyExc_TypeError,
154 "expected non-empty string "
155 "at tuple index 0");
156 return -1;
157 }
158
159 if (PyString_AS_STRING(st)[0] == skipchar)
160 continue; 147 continue;
161 } 148 }
162 149
163 if (_addpath(dirs, key) == -1) 150 if (_addpath(dirs, key) == -1)
164 return -1; 151 return -1;