Skip to content

Commit f74bdbe

Browse files
benpeartdscho
authored andcommitted
fscache: teach fscache to use mempool
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 <[email protected]>
1 parent 50e42c2 commit f74bdbe

File tree

1 file changed

+23
-21
lines changed

1 file changed

+23
-21
lines changed

compat/win32/fscache.c

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include "../win32.h"
44
#include "fscache.h"
55
#include "config.h"
6+
#include "../../mem-pool.h"
67

78
static volatile long initialized;
89
static DWORD dwTlsIndex;
@@ -17,6 +18,7 @@ static CRITICAL_SECTION mutex;
1718
struct fscache {
1819
volatile long enabled;
1920
struct hashmap map;
21+
struct mem_pool *mem_pool;
2022
unsigned int lstat_requests;
2123
unsigned int opendir_requests;
2224
unsigned int fscache_requests;
@@ -106,11 +108,11 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
106108
/*
107109
* Allocate an fsentry structure on the heap.
108110
*/
109-
static struct fsentry *fsentry_alloc(struct fsentry *list, const char *name,
111+
static struct fsentry *fsentry_alloc(struct fscache *cache, struct fsentry *list, const char *name,
110112
size_t len)
111113
{
112114
/* overallocate fsentry and copy the name to the end */
113-
struct fsentry *fse = xmalloc(sizeof(struct fsentry) + len + 1);
115+
struct fsentry *fse = mem_pool_alloc(cache->mem_pool, sizeof(struct fsentry) + len + 1);
114116
char *nm = ((char*) fse) + sizeof(struct fsentry);
115117
memcpy(nm, name, len);
116118
nm[len] = 0;
@@ -133,35 +135,28 @@ inline static void fsentry_addref(struct fsentry *fse)
133135
}
134136

135137
/*
136-
* Release the reference to an fsentry, frees the memory if its the last ref.
138+
* Release the reference to an fsentry.
137139
*/
138140
static void fsentry_release(struct fsentry *fse)
139141
{
140142
if (fse->list)
141143
fse = fse->list;
142144

143-
if (InterlockedDecrement(&(fse->refcnt)))
144-
return;
145-
146-
while (fse) {
147-
struct fsentry *next = fse->next;
148-
free(fse);
149-
fse = next;
150-
}
145+
InterlockedDecrement(&(fse->refcnt));
151146
}
152147

153148
/*
154149
* Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
155150
*/
156-
static struct fsentry *fseentry_create_entry(struct fsentry *list,
151+
static struct fsentry *fseentry_create_entry(struct fscache *cache, struct fsentry *list,
157152
const WIN32_FIND_DATAW *fdata)
158153
{
159154
char buf[MAX_PATH * 3];
160155
int len;
161156
struct fsentry *fse;
162157
len = xwcstoutf(buf, fdata->cFileName, ARRAY_SIZE(buf));
163158

164-
fse = fsentry_alloc(list, buf, len);
159+
fse = fsentry_alloc(cache, list, buf, len);
165160

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

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

246241
/* walk directory and build linked list of fsentry structures */
247242
phead = &list->next;
248243
do {
249-
*phead = fseentry_create_entry(list, &fdata);
244+
*phead = fseentry_create_entry(cache, list, &fdata);
250245
phead = &(*phead)->next;
251246
} while (FindNextFileW(h, &fdata));
252247

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

261-
/* otherwise free the list and return error */
256+
/* otherwise release the list and return error */
262257
fsentry_release(list);
263258
errno = err_win_to_posix(err);
264259
return NULL;
@@ -281,7 +276,10 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
281276
*/
282277
static void fscache_clear(struct fscache *cache)
283278
{
284-
hashmap_free(&cache->map, 1);
279+
mem_pool_discard(cache->mem_pool, 0);
280+
cache->mem_pool = NULL;
281+
mem_pool_init(&cache->mem_pool, 0);
282+
hashmap_free(&cache->map, 0);
285283
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, 0);
286284
cache->lstat_requests = cache->opendir_requests = 0;
287285
cache->fscache_misses = cache->fscache_requests = 0;
@@ -334,7 +332,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
334332
}
335333

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

339337
/* leave on error (errno set by fsentry_create_list) */
340338
if (!fse) {
@@ -344,7 +342,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
344342
* empty, which for all practical matters is the same
345343
* thing as far as fscache is concerned).
346344
*/
347-
fse = fsentry_alloc(key->list->list,
345+
fse = fsentry_alloc(cache, key->list->list,
348346
key->list->name, key->list->len);
349347
fse->st_mode = 0;
350348
hashmap_add(&cache->map, fse);
@@ -420,6 +418,7 @@ int fscache_enable(size_t initial_size)
420418
* '4' was determined empirically by testing several repos
421419
*/
422420
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, initial_size * 4);
421+
mem_pool_init(&cache->mem_pool, 0);
423422
if (!TlsSetValue(dwTlsIndex, cache))
424423
BUG("TlsSetValue error");
425424
}
@@ -451,7 +450,8 @@ void fscache_disable(void)
451450
"total requests/misses %u/%u\n",
452451
cache->lstat_requests, cache->opendir_requests,
453452
cache->fscache_requests, cache->fscache_misses);
454-
fscache_clear(cache);
453+
mem_pool_discard(cache->mem_pool, 0);
454+
hashmap_free(&cache->map, 0);
455455
free(cache);
456456
}
457457

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

637+
mem_pool_combine(dest->mem_pool, cache->mem_pool);
638+
637639
dest->lstat_requests += cache->lstat_requests;
638640
dest->opendir_requests += cache->opendir_requests;
639641
dest->fscache_requests += cache->fscache_requests;

0 commit comments

Comments
 (0)