Skip to content

Commit 68492fc

Browse files
Lars Knollgitster
authored andcommitted
Speedup scanning for excluded files.
Try to avoid a lot of work scanning for excluded files, by caching some more information when setting up the exclusion data structure. Speeds up 'git runstatus' on a repository containing the Qt sources by 30% and reduces the amount of instructions executed (as measured by valgrind) by a factor of 2. Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent 79f3368 commit 68492fc

File tree

2 files changed

+50
-16
lines changed

2 files changed

+50
-16
lines changed

dir.c

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -118,14 +118,32 @@ int match_pathspec(const char **pathspec, const char *name, int namelen, int pre
118118
return retval;
119119
}
120120

121+
static int no_wildcard(const char *string)
122+
{
123+
return string[strcspn(string, "*?[{")] == '\0';
124+
}
125+
121126
void add_exclude(const char *string, const char *base,
122127
int baselen, struct exclude_list *which)
123128
{
124129
struct exclude *x = xmalloc(sizeof (*x));
125130

131+
x->to_exclude = 1;
132+
if (*string == '!') {
133+
x->to_exclude = 0;
134+
string++;
135+
}
126136
x->pattern = string;
137+
x->patternlen = strlen(string);
127138
x->base = base;
128139
x->baselen = baselen;
140+
x->flags = 0;
141+
if (!strchr(string, '/'))
142+
x->flags |= EXC_FLAG_NODIR;
143+
if (no_wildcard(string))
144+
x->flags |= EXC_FLAG_NOWILDCARD;
145+
if (*string == '*' && no_wildcard(string+1))
146+
x->flags |= EXC_FLAG_ENDSWITH;
129147
if (which->nr == which->alloc) {
130148
which->alloc = alloc_nr(which->alloc);
131149
which->excludes = xrealloc(which->excludes,
@@ -209,7 +227,7 @@ void pop_exclude_per_directory(struct dir_struct *dir, int stk)
209227
* Return 1 for exclude, 0 for include and -1 for undecided.
210228
*/
211229
static int excluded_1(const char *pathname,
212-
int pathlen,
230+
int pathlen, const char *basename,
213231
struct exclude_list *el)
214232
{
215233
int i;
@@ -218,19 +236,21 @@ static int excluded_1(const char *pathname,
218236
for (i = el->nr - 1; 0 <= i; i--) {
219237
struct exclude *x = el->excludes[i];
220238
const char *exclude = x->pattern;
221-
int to_exclude = 1;
239+
int to_exclude = x->to_exclude;
222240

223-
if (*exclude == '!') {
224-
to_exclude = 0;
225-
exclude++;
226-
}
227-
228-
if (!strchr(exclude, '/')) {
241+
if (x->flags & EXC_FLAG_NODIR) {
229242
/* match basename */
230-
const char *basename = strrchr(pathname, '/');
231-
basename = (basename) ? basename+1 : pathname;
232-
if (fnmatch(exclude, basename, 0) == 0)
233-
return to_exclude;
243+
if (x->flags & EXC_FLAG_NOWILDCARD) {
244+
if (!strcmp(exclude, basename))
245+
return to_exclude;
246+
} else if (x->flags & EXC_FLAG_ENDSWITH) {
247+
if (x->patternlen - 1 <= pathlen &&
248+
!strcmp(exclude + 1, pathname + pathlen - x->patternlen + 1))
249+
return to_exclude;
250+
} else {
251+
if (fnmatch(exclude, basename, 0) == 0)
252+
return to_exclude;
253+
}
234254
}
235255
else {
236256
/* match with FNM_PATHNAME:
@@ -246,9 +266,14 @@ static int excluded_1(const char *pathname,
246266
strncmp(pathname, x->base, baselen))
247267
continue;
248268

249-
if (fnmatch(exclude, pathname+baselen,
250-
FNM_PATHNAME) == 0)
251-
return to_exclude;
269+
if (x->flags & EXC_FLAG_NOWILDCARD) {
270+
if (!strcmp(exclude, pathname + baselen))
271+
return to_exclude;
272+
} else {
273+
if (fnmatch(exclude, pathname+baselen,
274+
FNM_PATHNAME) == 0)
275+
return to_exclude;
276+
}
252277
}
253278
}
254279
}
@@ -259,9 +284,11 @@ int excluded(struct dir_struct *dir, const char *pathname)
259284
{
260285
int pathlen = strlen(pathname);
261286
int st;
287+
const char *basename = strrchr(pathname, '/');
288+
basename = (basename) ? basename+1 : pathname;
262289

263290
for (st = EXC_CMDL; st <= EXC_FILE; st++) {
264-
switch (excluded_1(pathname, pathlen, &dir->exclude_list[st])) {
291+
switch (excluded_1(pathname, pathlen, basename, &dir->exclude_list[st])) {
265292
case 0:
266293
return 0;
267294
case 1:

dir.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,20 @@ struct dir_entry {
1717
char name[FLEX_ARRAY]; /* more */
1818
};
1919

20+
#define EXC_FLAG_NODIR 1
21+
#define EXC_FLAG_NOWILDCARD 2
22+
#define EXC_FLAG_ENDSWITH 4
23+
2024
struct exclude_list {
2125
int nr;
2226
int alloc;
2327
struct exclude {
2428
const char *pattern;
29+
int patternlen;
2530
const char *base;
2631
int baselen;
32+
int to_exclude;
33+
int flags;
2734
} **excludes;
2835
};
2936

0 commit comments

Comments
 (0)