dir.c: git-status: avoid is_excluded checks for tracked files
Checking if a file is in the index is much faster (hashtable lookup) than checking if the file is excluded (linear search over exclude patterns). Skip is_excluded checks for files: move the cache_name_exists check from treat_file to treat_one_path and return early if the file is tracked. This can safely be done as all other code paths also return path_ignored for tracked files, and dir_add_ignored skips tracked files as well. There's just one line left in treat_file, so move this to treat_one_path as well. Here's some performance data for git-status from the linux and WebKit repos (best of 10 runs on a Debian Linux on SSD, core.preloadIndex=true): | status | status --ignored | linux | WebKit | linux | WebKit -------+-------+--------+-------+--------- before | 0.218 | 1.583 | 0.321 | 2.579 after | 0.156 | 0.988 | 0.202 | 1.279 gain | 1.397 | 1.602 | 1.589 | 2.016 Signed-off-by: Karsten Blees <blees@dcon.de> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
b07bc8c8c3
commit
8aaf8d7728
38
dir.c
38
dir.c
@ -1066,28 +1066,6 @@ static enum directory_treatment treat_directory(struct dir_struct *dir,
|
||||
return show_directory;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decide what to do when we find a file while traversing the
|
||||
* filesystem. Mostly two cases:
|
||||
*
|
||||
* 1. We are looking for ignored files
|
||||
* (a) File is ignored, include it
|
||||
* (b) File is in ignored path, include it
|
||||
* (c) File is not ignored, exclude it
|
||||
*
|
||||
* 2. Other scenarios, include the file if not excluded
|
||||
*
|
||||
* Return 1 for exclude, 0 for include.
|
||||
*/
|
||||
static int treat_file(struct dir_struct *dir, struct strbuf *path, int exclude)
|
||||
{
|
||||
/* Always exclude indexed files */
|
||||
if (index_name_exists(&the_index, path->buf, path->len, ignore_case))
|
||||
return 1;
|
||||
|
||||
return exclude == !(dir->flags & DIR_SHOW_IGNORED);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is an inexact early pruning of any recursive directory
|
||||
* reading - if the path cannot possibly be in the pathspec,
|
||||
@ -1211,7 +1189,16 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
|
||||
const struct path_simplify *simplify,
|
||||
int dtype, struct dirent *de)
|
||||
{
|
||||
int exclude = is_excluded(dir, path->buf, &dtype);
|
||||
int exclude;
|
||||
if (dtype == DT_UNKNOWN)
|
||||
dtype = get_dtype(de, path->buf, path->len);
|
||||
|
||||
/* Always exclude indexed files */
|
||||
if (dtype != DT_DIR &&
|
||||
cache_name_exists(path->buf, path->len, ignore_case))
|
||||
return path_ignored;
|
||||
|
||||
exclude = is_excluded(dir, path->buf, &dtype);
|
||||
if (exclude && (dir->flags & DIR_COLLECT_IGNORED)
|
||||
&& exclude_matches_pathspec(path->buf, path->len, simplify))
|
||||
dir_add_ignored(dir, path->buf, path->len);
|
||||
@ -1223,9 +1210,6 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
|
||||
if (exclude && !(dir->flags & DIR_SHOW_IGNORED))
|
||||
return path_ignored;
|
||||
|
||||
if (dtype == DT_UNKNOWN)
|
||||
dtype = get_dtype(de, path->buf, path->len);
|
||||
|
||||
switch (dtype) {
|
||||
default:
|
||||
return path_ignored;
|
||||
@ -1242,7 +1226,7 @@ static enum path_treatment treat_one_path(struct dir_struct *dir,
|
||||
break;
|
||||
case DT_REG:
|
||||
case DT_LNK:
|
||||
if (treat_file(dir, path, exclude))
|
||||
if (exclude == !(dir->flags & DIR_SHOW_IGNORED))
|
||||
return path_ignored;
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user