Skip to content

Commit 9ea4beb

Browse files
benpeartGit for Windows Build Agent
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 <benpeart@microsoft.com> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
1 parent 0bbed32 commit 9ea4beb

1 file changed

Lines changed: 24 additions & 21 deletions

File tree

compat/win32/fscache.c

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "../../abspath.h"
77
#include "../../trace.h"
88
#include "config.h"
9+
#include "../../mem-pool.h"
910

1011
static volatile long initialized;
1112
static DWORD dwTlsIndex;
@@ -20,6 +21,7 @@ static CRITICAL_SECTION mutex;
2021
struct fscache {
2122
volatile long enabled;
2223
struct hashmap map;
24+
struct mem_pool mem_pool;
2325
unsigned int lstat_requests;
2426
unsigned int opendir_requests;
2527
unsigned int fscache_requests;
@@ -129,11 +131,12 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
129131
/*
130132
* Allocate an fsentry structure on the heap.
131133
*/
132-
static struct fsentry *fsentry_alloc(struct fsentry *list, const char *name,
134+
static struct fsentry *fsentry_alloc(struct fscache *cache, struct fsentry *list, const char *name,
133135
size_t len)
134136
{
135137
/* overallocate fsentry and copy the name to the end */
136-
struct fsentry *fse = xmalloc(sizeof(struct fsentry) + len + 1);
138+
struct fsentry *fse =
139+
mem_pool_alloc(&cache->mem_pool, sizeof(*fse) + len + 1);
137140
/* init the rest of the structure */
138141
fsentry_init(fse, list, name, len);
139142
fse->next = NULL;
@@ -153,35 +156,29 @@ inline static void fsentry_addref(struct fsentry *fse)
153156
}
154157

155158
/*
156-
* Release the reference to an fsentry, frees the memory if its the last ref.
159+
* Release the reference to an fsentry.
157160
*/
158161
static void fsentry_release(struct fsentry *fse)
159162
{
160163
if (fse->list)
161164
fse = fse->list;
162165

163-
if (InterlockedDecrement(&(fse->u.refcnt)))
164-
return;
165-
166-
while (fse) {
167-
struct fsentry *next = fse->next;
168-
free(fse);
169-
fse = next;
170-
}
166+
InterlockedDecrement(&(fse->u.refcnt));
171167
}
172168

173169
/*
174170
* Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
175171
*/
176-
static struct fsentry *fseentry_create_entry(struct fsentry *list,
172+
static struct fsentry *fseentry_create_entry(struct fscache *cache,
173+
struct fsentry *list,
177174
const WIN32_FIND_DATAW *fdata)
178175
{
179176
char buf[MAX_PATH * 3];
180177
int len;
181178
struct fsentry *fse;
182179
len = xwcstoutf(buf, fdata->cFileName, ARRAY_SIZE(buf));
183180

184-
fse = fsentry_alloc(list, buf, len);
181+
fse = fsentry_alloc(cache, list, buf, len);
185182

186183
fse->st_mode = file_attr_to_st_mode(fdata->FileAttributes,
187184
fdata->EaSize);
@@ -201,7 +198,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
201198
* Dir should not contain trailing '/'. Use an empty string for the current
202199
* directory (not "."!).
203200
*/
204-
static struct fsentry *fsentry_create_list(const struct fsentry *dir,
201+
static struct fsentry *fsentry_create_list(struct fscache *cache, const struct fsentry *dir,
205202
int *dir_not_found)
206203
{
207204
wchar_t pattern[MAX_PATH + 2]; /* + 2 for '/' '*' */
@@ -240,14 +237,14 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
240237
}
241238

242239
/* allocate object to hold directory listing */
243-
list = fsentry_alloc(NULL, dir->dirent.d_name, dir->len);
240+
list = fsentry_alloc(cache, NULL, dir->dirent.d_name, dir->len);
244241
list->st_mode = S_IFDIR;
245242
list->dirent.d_type = DT_DIR;
246243

247244
/* walk directory and build linked list of fsentry structures */
248245
phead = &list->next;
249246
do {
250-
*phead = fseentry_create_entry(list, &fdata);
247+
*phead = fseentry_create_entry(cache, list, &fdata);
251248
phead = &(*phead)->next;
252249
} while (FindNextFileW(h, &fdata));
253250

@@ -259,7 +256,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
259256
if (err == ERROR_NO_MORE_FILES)
260257
return list;
261258

262-
/* otherwise free the list and return error */
259+
/* otherwise release the list and return error */
263260
fsentry_release(list);
264261
errno = err_win_to_posix(err);
265262
return NULL;
@@ -282,7 +279,9 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
282279
*/
283280
static void fscache_clear(struct fscache *cache)
284281
{
285-
hashmap_clear_and_free(&cache->map, struct fsentry, ent);
282+
mem_pool_discard(&cache->mem_pool, 0);
283+
mem_pool_init(&cache->mem_pool, 0);
284+
hashmap_clear(&cache->map);
286285
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, 0);
287286
cache->lstat_requests = cache->opendir_requests = 0;
288287
cache->fscache_misses = cache->fscache_requests = 0;
@@ -335,7 +334,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
335334
}
336335

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

340339
/* leave on error (errno set by fsentry_create_list) */
341340
if (!fse) {
@@ -345,7 +344,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
345344
* empty, which for all practical matters is the same
346345
* thing as far as fscache is concerned).
347346
*/
348-
fse = fsentry_alloc(key->list->list,
347+
fse = fsentry_alloc(cache, key->list->list,
349348
key->list->dirent.d_name,
350349
key->list->len);
351350
fse->st_mode = 0;
@@ -424,6 +423,7 @@ int fscache_enable(size_t initial_size)
424423
* '4' was determined empirically by testing several repos
425424
*/
426425
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, initial_size * 4);
426+
mem_pool_init(&cache->mem_pool, 0);
427427
if (!TlsSetValue(dwTlsIndex, cache))
428428
BUG("TlsSetValue error");
429429
}
@@ -455,7 +455,8 @@ void fscache_disable(void)
455455
"total requests/misses %u/%u\n",
456456
cache->lstat_requests, cache->opendir_requests,
457457
cache->fscache_requests, cache->fscache_misses);
458-
fscache_clear(cache);
458+
mem_pool_discard(&cache->mem_pool, 0);
459+
hashmap_clear(&cache->map);
459460
free(cache);
460461
}
461462

@@ -657,6 +658,8 @@ void fscache_merge(struct fscache *dest)
657658
while ((e = hashmap_iter_next(&iter)))
658659
hashmap_add(&dest->map, e);
659660

661+
mem_pool_combine(&dest->mem_pool, &cache->mem_pool);
662+
660663
dest->lstat_requests += cache->lstat_requests;
661664
dest->opendir_requests += cache->opendir_requests;
662665
dest->fscache_requests += cache->fscache_requests;

0 commit comments

Comments
 (0)