Skip to content

Commit 300d90d

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 950bfe2 commit 300d90d

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
if (fdata->dwReserved0 == IO_REPARSE_TAG_SYMLINK &&
167162
sizeof(buf) > (list ? list->len + 1 : 0) + fse->len + 1 &&
@@ -192,7 +187,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
192187
* Dir should not contain trailing '/'. Use an empty string for the current
193188
* directory (not "."!).
194189
*/
195-
static struct fsentry *fsentry_create_list(const struct fsentry *dir,
190+
static struct fsentry *fsentry_create_list(struct fscache *cache, const struct fsentry *dir,
196191
int *dir_not_found)
197192
{
198193
wchar_t pattern[MAX_LONG_PATH + 2]; /* + 2 for "\*" */
@@ -231,13 +226,13 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
231226
}
232227

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

237232
/* walk directory and build linked list of fsentry structures */
238233
phead = &list->next;
239234
do {
240-
*phead = fseentry_create_entry(list, &fdata);
235+
*phead = fseentry_create_entry(cache, list, &fdata);
241236
phead = &(*phead)->next;
242237
} while (FindNextFileW(h, &fdata));
243238

@@ -249,7 +244,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
249244
if (err == ERROR_NO_MORE_FILES)
250245
return list;
251246

252-
/* otherwise free the list and return error */
247+
/* otherwise release the list and return error */
253248
fsentry_release(list);
254249
errno = err_win_to_posix(err);
255250
return NULL;
@@ -272,7 +267,10 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
272267
*/
273268
static void fscache_clear(struct fscache *cache)
274269
{
275-
hashmap_free(&cache->map, 1);
270+
mem_pool_discard(cache->mem_pool, 0);
271+
cache->mem_pool = NULL;
272+
mem_pool_init(&cache->mem_pool, 0);
273+
hashmap_free(&cache->map, 0);
276274
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, 0);
277275
cache->lstat_requests = cache->opendir_requests = 0;
278276
cache->fscache_misses = cache->fscache_requests = 0;
@@ -325,7 +323,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
325323
}
326324

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

330328
/* leave on error (errno set by fsentry_create_list) */
331329
if (!fse) {
@@ -335,7 +333,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
335333
* empty, which for all practical matters is the same
336334
* thing as far as fscache is concerned).
337335
*/
338-
fse = fsentry_alloc(key->list->list,
336+
fse = fsentry_alloc(cache, key->list->list,
339337
key->list->name, key->list->len);
340338
fse->st_mode = 0;
341339
hashmap_add(&cache->map, fse);
@@ -411,6 +409,7 @@ int fscache_enable(size_t initial_size)
411409
* '4' was determined empirically by testing several repos
412410
*/
413411
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, initial_size * 4);
412+
mem_pool_init(&cache->mem_pool, 0);
414413
if (!TlsSetValue(dwTlsIndex, cache))
415414
BUG("TlsSetValue error");
416415
}
@@ -442,7 +441,8 @@ void fscache_disable(void)
442441
"total requests/misses %u/%u\n",
443442
cache->lstat_requests, cache->opendir_requests,
444443
cache->fscache_requests, cache->fscache_misses);
445-
fscache_clear(cache);
444+
mem_pool_discard(cache->mem_pool, 0);
445+
hashmap_free(&cache->map, 0);
446446
free(cache);
447447
}
448448

@@ -625,6 +625,8 @@ void fscache_merge(struct fscache *dest)
625625
while ((e = hashmap_iter_next(&iter)))
626626
hashmap_add(&dest->map, e);
627627

628+
mem_pool_combine(dest->mem_pool, cache->mem_pool);
629+
628630
dest->lstat_requests += cache->lstat_requests;
629631
dest->opendir_requests += cache->opendir_requests;
630632
dest->fscache_requests += cache->fscache_requests;

0 commit comments

Comments
 (0)