mirror of
https://github.com/git-for-windows/git.git
synced 2026-04-07 02:07:35 -05:00
fsmonitor: optimize processing of directory events
Teach Git to perform binary search over the cache-entries for a directory notification and then linearly scan forward to find the immediate children. Previously, when the FSMonitor reported a modified directory Git would perform a linear search on the entire cache-entry array for all entries matching that directory prefix and invalidate them. Since the cache-entry array is already sorted, we can use a binary search to find the first matching entry and then only linearly walk forward and invalidate entries until the prefix changes. Also, the original code would invalidate anything having the same directory prefix. Since a directory event should only be received for items that are immediately within the directory (and not within sub-directories of it), only invalidate those entries and not the whole subtree. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
This commit is contained in:
committed by
Johannes Schindelin
parent
edb45f063b
commit
13f8336b2b
23
fsmonitor.c
23
fsmonitor.c
@@ -199,25 +199,24 @@ static void fsmonitor_refresh_callback(struct index_state *istate, char *name)
|
||||
{
|
||||
int i, len = strlen(name);
|
||||
if (name[len - 1] == '/') {
|
||||
|
||||
/*
|
||||
* TODO We should binary search to find the first path with
|
||||
* TODO this directory prefix. Then linearly update entries
|
||||
* TODO while the prefix matches. Taking care to search without
|
||||
* TODO the trailing slash -- because '/' sorts after a few
|
||||
* TODO interesting special chars, like '.' and ' '.
|
||||
*/
|
||||
const char *rel;
|
||||
int pos = index_name_pos(istate, name, len);
|
||||
if (pos < 0)
|
||||
pos = -pos - 1;
|
||||
|
||||
/* Mark all entries for the folder invalid */
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
if (istate->cache[i]->ce_flags & CE_FSMONITOR_VALID &&
|
||||
starts_with(istate->cache[i]->name, name))
|
||||
for (i = pos; i < istate->cache_nr; i++) {
|
||||
if (!starts_with(istate->cache[i]->name, name))
|
||||
break;
|
||||
/* Only mark the immediate children in the folder */
|
||||
rel = istate->cache[i]->name + len;
|
||||
if (!strchr(rel, '/'))
|
||||
istate->cache[i]->ce_flags &= ~CE_FSMONITOR_VALID;
|
||||
}
|
||||
/* Need to remove the / from the path for the untracked cache */
|
||||
name[len - 1] = '\0';
|
||||
} else {
|
||||
int pos = index_name_pos(istate, name, strlen(name));
|
||||
int pos = index_name_pos(istate, name, len);
|
||||
|
||||
if (pos >= 0) {
|
||||
struct cache_entry *ce = istate->cache[pos];
|
||||
|
||||
Reference in New Issue
Block a user