Skip to content

Commit

Permalink
dir.c: make add_excludes aware of fscache during status
Browse files Browse the repository at this point in the history
Teach read_directory_recursive() and add_excludes() to
be aware of optional fscache and avoid trying to open()
and fstat() non-existant ".gitignore" files in every
directory in the worktree.

The current code in add_excludes() calls open() and then
fstat() for a ".gitignore" file in each directory present
in the worktree.  Change that when fscache is enabled to
call lstat() first and if present, call open().

This seems backwards because both lstat needs to do more
work than fstat.  But when fscache is enabled, fscache will
already know if the .gitignore file exists and can completely
avoid the IO calls.  This works because of the lstat diversion
to mingw_lstat when fscache is enabled.

This reduced status times on a 350K file enlistment of the
Windows repo on a NVMe SSD by 0.25 seconds.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
  • Loading branch information
jeffhostetler authored and dscho committed Sep 16, 2022
1 parent 137482a commit 47cf2b5
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 9 deletions.
5 changes: 5 additions & 0 deletions compat/win32/fscache.c
Expand Up @@ -10,6 +10,11 @@ static struct hashmap map;
static CRITICAL_SECTION mutex;
static struct trace_key trace_fscache = TRACE_KEY_INIT(FSCACHE);

int fscache_is_enabled(void)
{
return enabled;
}

/*
* An entry in the file system cache. Used for both entire directory listings
* and file entries.
Expand Down
3 changes: 3 additions & 0 deletions compat/win32/fscache.h
Expand Up @@ -4,6 +4,9 @@
int fscache_enable(int enable);
#define enable_fscache(x) fscache_enable(x)

int fscache_is_enabled(void);
#define is_fscache_enabled() (fscache_is_enabled())

DIR *fscache_opendir(const char *dir);
int fscache_lstat(const char *file_name, struct stat *buf);

Expand Down
33 changes: 24 additions & 9 deletions dir.c
Expand Up @@ -1063,16 +1063,31 @@ static int add_patterns(const char *fname, const char *base, int baselen,
size_t size = 0;
char *buf;

if (flags & PATTERN_NOFOLLOW)
fd = open_nofollow(fname, O_RDONLY);
else
fd = open(fname, O_RDONLY);

if (fd < 0 || fstat(fd, &st) < 0) {
if (fd < 0)
warn_on_fopen_errors(fname);
if (is_fscache_enabled()) {
if (lstat(fname, &st) < 0) {
fd = -1;
} else {
fd = open(fname, O_RDONLY);
if (fd < 0)
warn_on_fopen_errors(fname);
}
} else {
if (flags & PATTERN_NOFOLLOW)
fd = open_nofollow(fname, O_RDONLY);
else
close(fd);
fd = open(fname, O_RDONLY);

if (fd < 0 || fstat(fd, &st) < 0) {
if (fd < 0)
warn_on_fopen_errors(fname);
else {
close(fd);
fd = -1;
}
}
}

if (fd < 0) {
if (!istate)
return -1;
r = read_skip_worktree_file_from_index(istate, fname,
Expand Down
4 changes: 4 additions & 0 deletions git-compat-util.h
Expand Up @@ -1544,6 +1544,10 @@ static inline int is_missing_file_error(int errno_)
#define enable_fscache(x) /* noop */
#endif

#ifndef is_fscache_enabled
#define is_fscache_enabled() (0)
#endif

int cmd_main(int, const char **);

/*
Expand Down

0 comments on commit 47cf2b5

Please sign in to comment.