Skip to content

Commit d5eaf00

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 073a51a commit d5eaf00

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->u.refcnt)))
144-
return;
145-
146-
while (fse) {
147-
struct fsentry *next = fse->next;
148-
free(fse);
149-
fse = next;
150-
}
145+
InterlockedDecrement(&(fse->u.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
fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes);
167162
fse->u.s.st_size = (((off64_t) (fdata->nFileSizeHigh)) << 32)
@@ -178,7 +173,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
178173
* Dir should not contain trailing '/'. Use an empty string for the current
179174
* directory (not "."!).
180175
*/
181-
static struct fsentry *fsentry_create_list(const struct fsentry *dir,
176+
static struct fsentry *fsentry_create_list(struct fscache *cache, const struct fsentry *dir,
182177
int *dir_not_found)
183178
{
184179
wchar_t pattern[MAX_PATH + 2]; /* + 2 for '/' '*' */
@@ -216,13 +211,13 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
216211
}
217212

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

222217
/* walk directory and build linked list of fsentry structures */
223218
phead = &list->next;
224219
do {
225-
*phead = fseentry_create_entry(list, &fdata);
220+
*phead = fseentry_create_entry(cache, list, &fdata);
226221
phead = &(*phead)->next;
227222
} while (FindNextFileW(h, &fdata));
228223

@@ -234,7 +229,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
234229
if (err == ERROR_NO_MORE_FILES)
235230
return list;
236231

237-
/* otherwise free the list and return error */
232+
/* otherwise release the list and return error */
238233
fsentry_release(list);
239234
errno = err_win_to_posix(err);
240235
return NULL;
@@ -257,7 +252,10 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
257252
*/
258253
static void fscache_clear(struct fscache *cache)
259254
{
260-
hashmap_free(&cache->map, 1);
255+
mem_pool_discard(cache->mem_pool, 0);
256+
cache->mem_pool = NULL;
257+
mem_pool_init(&cache->mem_pool, 0);
258+
hashmap_free(&cache->map, 0);
261259
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, 0);
262260
cache->lstat_requests = cache->opendir_requests = 0;
263261
cache->fscache_misses = cache->fscache_requests = 0;
@@ -310,7 +308,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
310308
}
311309

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

315313
/* leave on error (errno set by fsentry_create_list) */
316314
if (!fse) {
@@ -320,7 +318,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
320318
* empty, which for all practical matters is the same
321319
* thing as far as fscache is concerned).
322320
*/
323-
fse = fsentry_alloc(key->list->list,
321+
fse = fsentry_alloc(cache, key->list->list,
324322
key->list->name, key->list->len);
325323
fse->st_mode = 0;
326324
hashmap_add(&cache->map, fse);
@@ -398,6 +396,7 @@ int fscache_enable(size_t initial_size)
398396
* '4' was determined empirically by testing several repos
399397
*/
400398
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, initial_size * 4);
399+
mem_pool_init(&cache->mem_pool, 0);
401400
if (!TlsSetValue(dwTlsIndex, cache))
402401
BUG("TlsSetValue error");
403402
}
@@ -429,7 +428,8 @@ void fscache_disable(void)
429428
"total requests/misses %u/%u\n",
430429
cache->lstat_requests, cache->opendir_requests,
431430
cache->fscache_requests, cache->fscache_misses);
432-
fscache_clear(cache);
431+
mem_pool_discard(cache->mem_pool, 0);
432+
hashmap_free(&cache->map, 0);
433433
free(cache);
434434
}
435435

@@ -611,6 +611,8 @@ void fscache_merge(struct fscache *dest)
611611
while ((e = hashmap_iter_next(&iter)))
612612
hashmap_add(&dest->map, e);
613613

614+
mem_pool_combine(dest->mem_pool, cache->mem_pool);
615+
614616
dest->lstat_requests += cache->lstat_requests;
615617
dest->opendir_requests += cache->opendir_requests;
616618
dest->fscache_requests += cache->fscache_requests;

0 commit comments

Comments
 (0)