Skip to content

Commit ff895c0

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 fe88050 commit ff895c0

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
fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes);
167162
fse->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_LONG_PATH + 2]; /* + 2 for "\*" */
@@ -217,13 +212,13 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
217212
}
218213

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

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

@@ -235,7 +230,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
235230
if (err == ERROR_NO_MORE_FILES)
236231
return list;
237232

238-
/* otherwise free the list and return error */
233+
/* otherwise release the list and return error */
239234
fsentry_release(list);
240235
errno = err_win_to_posix(err);
241236
return NULL;
@@ -258,7 +253,10 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
258253
*/
259254
static void fscache_clear(struct fscache *cache)
260255
{
261-
hashmap_free(&cache->map, 1);
256+
mem_pool_discard(cache->mem_pool, 0);
257+
cache->mem_pool = NULL;
258+
mem_pool_init(&cache->mem_pool, 0);
259+
hashmap_free(&cache->map, 0);
262260
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, 0);
263261
cache->lstat_requests = cache->opendir_requests = 0;
264262
cache->fscache_misses = cache->fscache_requests = 0;
@@ -311,7 +309,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
311309
}
312310

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

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

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

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

0 commit comments

Comments
 (0)