* [PATCH] runstatus: do not recurse into subdirectories if not needed @ 2006-09-27 11:16 Johannes Schindelin 2006-09-28 0:09 ` Junio C Hamano 0 siblings, 1 reply; 5+ messages in thread From: Johannes Schindelin @ 2006-09-27 11:16 UTC (permalink / raw) To: git, junkio This speeds up the case when you run git-status, having an untracked subdirectory containing huge amounts of files. It also clarifies the handling of hide_empty_directories; the old version worked, but was hard to understand. Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> --- dir.c | 24 +++++++++++++++--------- 1 files changed, 15 insertions(+), 9 deletions(-) diff --git a/dir.c b/dir.c index e2f472b..e69663c 100644 --- a/dir.c +++ b/dir.c @@ -274,6 +274,15 @@ static int dir_exists(const char *dirnam return !strncmp(active_cache[pos]->name, dirname, len); } +static int dir_is_empty(const char *dirname) +{ + DIR *fdir = opendir(dirname); + int result = (readdir(fdir) == NULL); + + closedir(fdir); + return result; +} + /* * Read a directory tree. We currently ignore anything but * directories, regular files and symlinks. That's because git @@ -314,7 +323,6 @@ static int read_directory_recursive(stru switch (DTYPE(de)) { struct stat st; - int subdir, rewind_base; default: continue; case DT_UNKNOWN: @@ -328,18 +336,16 @@ static int read_directory_recursive(stru case DT_DIR: memcpy(fullname + baselen + len, "/", 2); len++; - rewind_base = dir->nr; - subdir = read_directory_recursive(dir, fullname, fullname, - baselen + len); if (dir->show_other_directories && - (subdir || !dir->hide_empty_directories) && !dir_exists(fullname, baselen + len)) { - /* Rewind the read subdirectory */ - while (dir->nr > rewind_base) - free(dir->entries[--dir->nr]); + if (dir->hide_empty_directories && + dir_is_empty(fullname)) + continue; break; } - contents += subdir; + + contents += read_directory_recursive(dir, + fullname, fullname, baselen + len); continue; case DT_REG: case DT_LNK: -- 1.4.2.1.g78cd-dirty ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] runstatus: do not recurse into subdirectories if not needed 2006-09-27 11:16 [PATCH] runstatus: do not recurse into subdirectories if not needed Johannes Schindelin @ 2006-09-28 0:09 ` Junio C Hamano 2006-09-28 0:26 ` Johannes Schindelin 0 siblings, 1 reply; 5+ messages in thread From: Junio C Hamano @ 2006-09-28 0:09 UTC (permalink / raw) To: Johannes Schindelin; +Cc: git Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: > This speeds up the case when you run git-status, having an untracked > subdirectory containing huge amounts of files. > > It also clarifies the handling of hide_empty_directories; the old version > worked, but was hard to understand. > > Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> > --- > dir.c | 24 +++++++++++++++--------- > 1 files changed, 15 insertions(+), 9 deletions(-) > > diff --git a/dir.c b/dir.c > index e2f472b..e69663c 100644 > --- a/dir.c > +++ b/dir.c > @@ -274,6 +274,15 @@ static int dir_exists(const char *dirnam > return !strncmp(active_cache[pos]->name, dirname, len); > } > > +static int dir_is_empty(const char *dirname) > +{ > + DIR *fdir = opendir(dirname); > + int result = (readdir(fdir) == NULL); > + > + closedir(fdir); > + return result; > +} > + Does this really check if the directory is empty (I think you would read "." and ".." out of it at least)? When the original code recurses into subdirectory, it seems to behave identically for a truly empty directory and a directory that has only ".git" (or excluded files in it under !show_ignored). ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] runstatus: do not recurse into subdirectories if not needed 2006-09-28 0:09 ` Junio C Hamano @ 2006-09-28 0:26 ` Johannes Schindelin 2006-09-28 0:44 ` [PATCH 2nd try] " Johannes Schindelin 0 siblings, 1 reply; 5+ messages in thread From: Johannes Schindelin @ 2006-09-28 0:26 UTC (permalink / raw) To: Junio C Hamano; +Cc: git Hi, On Wed, 27 Sep 2006, Junio C Hamano wrote: > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: > > > This speeds up the case when you run git-status, having an untracked > > subdirectory containing huge amounts of files. > > > > It also clarifies the handling of hide_empty_directories; the old version > > worked, but was hard to understand. > > > > Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> > > --- > > dir.c | 24 +++++++++++++++--------- > > 1 files changed, 15 insertions(+), 9 deletions(-) > > > > diff --git a/dir.c b/dir.c > > index e2f472b..e69663c 100644 > > --- a/dir.c > > +++ b/dir.c > > @@ -274,6 +274,15 @@ static int dir_exists(const char *dirnam > > return !strncmp(active_cache[pos]->name, dirname, len); > > } > > > > +static int dir_is_empty(const char *dirname) > > +{ > > + DIR *fdir = opendir(dirname); > > + int result = (readdir(fdir) == NULL); > > + > > + closedir(fdir); > > + return result; > > +} > > + > > Does this really check if the directory is empty (I think you > would read "." and ".." out of it at least)? > > When the original code recurses into subdirectory, it seems to > behave identically for a truly empty directory and a directory > that has only ".git" (or excluded files in it under !show_ignored). Of course I missed that. Probably, because there is no test for that. But given my experience of a very, _very_ slow git-status when I do not _care_ about that particular directory (even if it does contain .git and excluded files), is it really sensible to have _no_ way to disable hide_empty_directories when show_other_directories is enabled? Or would it make sense to disable hide_empty_directories altogether? Now, I could enhance dir_is_empty() to recursively test if the dir is empty, and return 0 on first sight of a not-excluded dir entry, but is it really worth the hassle? Ciao, Dscho ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2nd try] runstatus: do not recurse into subdirectories if not needed 2006-09-28 0:26 ` Johannes Schindelin @ 2006-09-28 0:44 ` Johannes Schindelin 2006-09-28 4:40 ` Junio C Hamano 0 siblings, 1 reply; 5+ messages in thread From: Johannes Schindelin @ 2006-09-28 0:44 UTC (permalink / raw) To: Junio C Hamano; +Cc: git This speeds up the case when you run git-status, having an untracked subdirectory containing huge amounts of files. Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> --- On Thu, 28 Sep 2006, Johannes Schindelin wrote: > On Wed, 27 Sep 2006, Junio C Hamano wrote: > > > Does this really check if the directory is empty (I think you > > would read "." and ".." out of it at least)? > > > > When the original code recurses into subdirectory, it seems to > > behave identically for a truly empty directory and a directory > > that has only ".git" (or excluded files in it under > > !show_ignored). > > Of course I missed that. Probably, because there is no test for > that. > > [...] > > Now, I could enhance dir_is_empty() to recursively test if the > dir is empty, and return 0 on first sight of a not-excluded dir > entry, but is it really worth the hassle? Okay, so no more dir_is_empty(). Instead, read_directory_recursive() gets a flag. With this flag, "check_only", it exits as soon as it found valid entries, but does not add any. Way easier. dir.c | 27 +++++++++++++++------------ 1 files changed, 15 insertions(+), 12 deletions(-) diff --git a/dir.c b/dir.c index e2f472b..96389b3 100644 --- a/dir.c +++ b/dir.c @@ -283,7 +283,7 @@ static int dir_exists(const char *dirnam * Also, we ignore the name ".git" (even if it is not a directory). * That likely will not change. */ -static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen) +static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only) { DIR *fdir = opendir(path); int contents = 0; @@ -314,7 +314,6 @@ static int read_directory_recursive(stru switch (DTYPE(de)) { struct stat st; - int subdir, rewind_base; default: continue; case DT_UNKNOWN: @@ -328,26 +327,30 @@ static int read_directory_recursive(stru case DT_DIR: memcpy(fullname + baselen + len, "/", 2); len++; - rewind_base = dir->nr; - subdir = read_directory_recursive(dir, fullname, fullname, - baselen + len); if (dir->show_other_directories && - (subdir || !dir->hide_empty_directories) && !dir_exists(fullname, baselen + len)) { - /* Rewind the read subdirectory */ - while (dir->nr > rewind_base) - free(dir->entries[--dir->nr]); + if (dir->hide_empty_directories && + !read_directory_recursive(dir, + fullname, fullname, + baselen + len, 1)) + continue; break; } - contents += subdir; + + contents += read_directory_recursive(dir, + fullname, fullname, baselen + len, 0); continue; case DT_REG: case DT_LNK: break; } - add_name(dir, fullname, baselen + len); contents++; + if (check_only) + goto exit_early; + else + add_name(dir, fullname, baselen + len); } +exit_early: closedir(fdir); pop_exclude_per_directory(dir, exclude_stk); @@ -393,7 +396,7 @@ int read_directory(struct dir_struct *di } } - read_directory_recursive(dir, path, base, baselen); + read_directory_recursive(dir, path, base, baselen, 0); qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name); return dir->nr; } ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 2nd try] runstatus: do not recurse into subdirectories if not needed 2006-09-28 0:44 ` [PATCH 2nd try] " Johannes Schindelin @ 2006-09-28 4:40 ` Junio C Hamano 0 siblings, 0 replies; 5+ messages in thread From: Junio C Hamano @ 2006-09-28 4:40 UTC (permalink / raw) To: Johannes Schindelin; +Cc: git Johannes Schindelin <Johannes.Schindelin@gmx.de> writes: > This speeds up the case when you run git-status, having an untracked > subdirectory containing huge amounts of files. > > Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> > > --- > > On Thu, 28 Sep 2006, Johannes Schindelin wrote: > > Okay, so no more dir_is_empty(). Instead, read_directory_recursive() > gets a flag. With this flag, "check_only", it exits as soon as it > found valid entries, but does not add any. Way easier. Yeah, the logic is a lot easier to follow. ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2006-09-28 4:40 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2006-09-27 11:16 [PATCH] runstatus: do not recurse into subdirectories if not needed Johannes Schindelin 2006-09-28 0:09 ` Junio C Hamano 2006-09-28 0:26 ` Johannes Schindelin 2006-09-28 0:44 ` [PATCH 2nd try] " Johannes Schindelin 2006-09-28 4:40 ` Junio C Hamano
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox