An implementation of stat(2) and lstat(2) caching. Both the return code and returned information are cached. Signed-off-by: Luciano Rocha <strange@xxxxxxxxxxxxx> --- On Sat, Apr 19, 2008 at 03:39:37PM -0700, Linus Torvalds wrote: > Yeah. I didn't look any further, but we do a total of *nine* 'lstat()' > calls for each file we know about that is dirty, and *seven* when they are > clean. Plus maybe a few more. That's a lot. Why not use a stat cache? With these changes, my git status . in WebKit changes from 28.215s to 15.414s. stat-cache.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ stat-cache.h | 9 +++++++ 2 files changed, 78 insertions(+), 0 deletions(-) create mode 100644 stat-cache.c create mode 100644 stat-cache.h diff --git a/stat-cache.c b/stat-cache.c new file mode 100644 index 0000000..6a33cec --- /dev/null +++ b/stat-cache.c @@ -0,0 +1,69 @@ +/* + * Cache (l)stat operations + */ + +#include "stat-cache.h" +#include "hash.h" +#include "path-list.h"; + +static struct hash_table stat_cache; +static struct hash_table lstat_cache; + +struct stat_result { + struct stat st; + int ret; +}; + +/* based on hash_name from read_cache.c */ +static unsigned int hash_path(const char *path) +{ + unsigned int hash = 0x123; + + while (*path) + hash = hash*101 + *path++; + return hash; +} + +/* cache is HASH->PATH-LIST->(return code, struct stat) */ +static int cached_stat(int (*f)(const char *, struct stat *), + struct hash_table *ht, const char *path, struct stat *buf) +{ + unsigned int hash; + struct path_list *list; + struct path_list_item *cached; + struct stat_result *result; + + hash = hash_path(path); + + list = lookup_hash(hash, ht); + + if (!list) { + list = xcalloc(1, sizeof *list); + list->strdup_paths = 1; + insert_hash(hash, list, ht); + } + + cached = path_list_lookup(path, list); + + if (cached) { + result = cached->util; + } else { + result = xmalloc(sizeof *result); + result->ret = f(path, &result->st); + path_list_insert(path, list)->util = result; + } + + if (result->ret == 0) + memcpy(buf, &result->st, sizeof *buf); + return result->ret; +} + +int cstat(const char *path, struct stat *buf) +{ + return cached_stat(stat, &stat_cache, path, buf); +} + +int clstat(const char *path, struct stat *buf) +{ + return cached_stat(lstat, &lstat_cache, path, buf); +} diff --git a/stat-cache.h b/stat-cache.h new file mode 100644 index 0000000..754348f --- /dev/null +++ b/stat-cache.h @@ -0,0 +1,9 @@ +#ifndef STAT_CACHE_H +#define STAT_CACHE_H + +#include "git-compat-util.h" + +int cstat(const char *path, struct stat *buf); +int clstat(const char *path, struct stat *buf); + +#endif /* STAT_CACHE_H */ -- 1.5.5.76.gbb45.dirty -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html