Skip to content

Commit

Permalink
fscache: teach fscache to use mempool
Browse files Browse the repository at this point in the history
Now that the fscache is single threaded, take advantage of the mem_pool as
the allocator to significantly reduce the cost of allocations and frees.

With the reduced cost of free, in future patches, we can start freeing the
fscache at the end of commands instead of just leaking it.

Signed-off-by: Ben Peart <benpeart@microsoft.com>
  • Loading branch information
benpeart authored and dscho committed Dec 9, 2018
1 parent 1c973df commit 4d0a394
Showing 1 changed file with 23 additions and 21 deletions.
44 changes: 23 additions & 21 deletions compat/win32/fscache.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "../win32.h"
#include "fscache.h"
#include "config.h"
#include "../../mem-pool.h"

static volatile long initialized;
static DWORD dwTlsIndex;
Expand All @@ -17,6 +18,7 @@ static CRITICAL_SECTION mutex;
struct fscache {
volatile long enabled;
struct hashmap map;
struct mem_pool *mem_pool;
unsigned int lstat_requests;
unsigned int opendir_requests;
unsigned int fscache_requests;
Expand Down Expand Up @@ -106,11 +108,11 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
/*
* Allocate an fsentry structure on the heap.
*/
static struct fsentry *fsentry_alloc(struct fsentry *list, const char *name,
static struct fsentry *fsentry_alloc(struct fscache *cache, struct fsentry *list, const char *name,
size_t len)
{
/* overallocate fsentry and copy the name to the end */
struct fsentry *fse = xmalloc(sizeof(struct fsentry) + len + 1);
struct fsentry *fse = mem_pool_alloc(cache->mem_pool, sizeof(struct fsentry) + len + 1);
char *nm = ((char*) fse) + sizeof(struct fsentry);
memcpy(nm, name, len);
nm[len] = 0;
Expand All @@ -133,35 +135,28 @@ inline static void fsentry_addref(struct fsentry *fse)
}

/*
* Release the reference to an fsentry, frees the memory if its the last ref.
* Release the reference to an fsentry.
*/
static void fsentry_release(struct fsentry *fse)
{
if (fse->list)
fse = fse->list;

if (InterlockedDecrement(&(fse->refcnt)))
return;

while (fse) {
struct fsentry *next = fse->next;
free(fse);
fse = next;
}
InterlockedDecrement(&(fse->refcnt));
}

/*
* Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
*/
static struct fsentry *fseentry_create_entry(struct fsentry *list,
static struct fsentry *fseentry_create_entry(struct fscache *cache, struct fsentry *list,
const WIN32_FIND_DATAW *fdata)
{
char buf[MAX_PATH * 3];
int len;
struct fsentry *fse;
len = xwcstoutf(buf, fdata->cFileName, ARRAY_SIZE(buf));

fse = fsentry_alloc(list, buf, len);
fse = fsentry_alloc(cache, list, buf, len);

/*
* On certain Windows versions, host directories mapped into
Expand Down Expand Up @@ -201,7 +196,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
* Dir should not contain trailing '/'. Use an empty string for the current
* directory (not "."!).
*/
static struct fsentry *fsentry_create_list(const struct fsentry *dir,
static struct fsentry *fsentry_create_list(struct fscache *cache, const struct fsentry *dir,
int *dir_not_found)
{
wchar_t pattern[MAX_LONG_PATH + 2]; /* + 2 for "\*" */
Expand Down Expand Up @@ -240,13 +235,13 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
}

/* allocate object to hold directory listing */
list = fsentry_alloc(NULL, dir->name, dir->len);
list = fsentry_alloc(cache, NULL, dir->name, dir->len);
list->st_mode = S_IFDIR;

/* walk directory and build linked list of fsentry structures */
phead = &list->next;
do {
*phead = fseentry_create_entry(list, &fdata);
*phead = fseentry_create_entry(cache, list, &fdata);
phead = &(*phead)->next;
} while (FindNextFileW(h, &fdata));

Expand All @@ -258,7 +253,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
if (err == ERROR_NO_MORE_FILES)
return list;

/* otherwise free the list and return error */
/* otherwise release the list and return error */
fsentry_release(list);
errno = err_win_to_posix(err);
return NULL;
Expand All @@ -281,7 +276,10 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
*/
static void fscache_clear(struct fscache *cache)
{
hashmap_free(&cache->map, 1);
mem_pool_discard(cache->mem_pool, 0);
cache->mem_pool = NULL;
mem_pool_init(&cache->mem_pool, 0);
hashmap_free(&cache->map, 0);
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, 0);
cache->lstat_requests = cache->opendir_requests = 0;
cache->fscache_misses = cache->fscache_requests = 0;
Expand Down Expand Up @@ -334,7 +332,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
}

/* create the directory listing */
fse = fsentry_create_list(key->list ? key->list : key, &dir_not_found);
fse = fsentry_create_list(cache, key->list ? key->list : key, &dir_not_found);

/* leave on error (errno set by fsentry_create_list) */
if (!fse) {
Expand All @@ -344,7 +342,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
* empty, which for all practical matters is the same
* thing as far as fscache is concerned).
*/
fse = fsentry_alloc(key->list->list,
fse = fsentry_alloc(cache, key->list->list,
key->list->name, key->list->len);
fse->st_mode = 0;
hashmap_add(&cache->map, fse);
Expand Down Expand Up @@ -420,6 +418,7 @@ int fscache_enable(size_t initial_size)
* '4' was determined empirically by testing several repos
*/
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, initial_size * 4);
mem_pool_init(&cache->mem_pool, 0);
if (!TlsSetValue(dwTlsIndex, cache))
BUG("TlsSetValue error");
}
Expand Down Expand Up @@ -451,7 +450,8 @@ void fscache_disable(void)
"total requests/misses %u/%u\n",
cache->lstat_requests, cache->opendir_requests,
cache->fscache_requests, cache->fscache_misses);
fscache_clear(cache);
mem_pool_discard(cache->mem_pool, 0);
hashmap_free(&cache->map, 0);
free(cache);
}

Expand Down Expand Up @@ -634,6 +634,8 @@ void fscache_merge(struct fscache *dest)
while ((e = hashmap_iter_next(&iter)))
hashmap_add(&dest->map, e);

mem_pool_combine(dest->mem_pool, cache->mem_pool);

dest->lstat_requests += cache->lstat_requests;
dest->opendir_requests += cache->opendir_requests;
dest->fscache_requests += cache->fscache_requests;
Expand Down

0 comments on commit 4d0a394

Please sign in to comment.