Skip to content

Commit 573d422

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]> Signed-off-by: Johannes Schindelin <[email protected]>
1 parent ecc4e79 commit 573d422

File tree

1 file changed

+24
-21
lines changed

1 file changed

+24
-21
lines changed

compat/win32/fscache.c

+24-21
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "fscache.h"
55
#include "../../dir.h"
66
#include "config.h"
7+
#include "../../mem-pool.h"
78

89
static volatile long initialized;
910
static DWORD dwTlsIndex;
@@ -18,6 +19,7 @@ static CRITICAL_SECTION mutex;
1819
struct fscache {
1920
volatile long enabled;
2021
struct hashmap map;
22+
struct mem_pool mem_pool;
2123
unsigned int lstat_requests;
2224
unsigned int opendir_requests;
2325
unsigned int fscache_requests;
@@ -122,11 +124,12 @@ static void fsentry_init(struct fsentry *fse, struct fsentry *list,
122124
/*
123125
* Allocate an fsentry structure on the heap.
124126
*/
125-
static struct fsentry *fsentry_alloc(struct fsentry *list, const char *name,
127+
static struct fsentry *fsentry_alloc(struct fscache *cache, struct fsentry *list, const char *name,
126128
size_t len)
127129
{
128130
/* overallocate fsentry and copy the name to the end */
129-
struct fsentry *fse = xmalloc(sizeof(struct fsentry) + len + 1);
131+
struct fsentry *fse =
132+
mem_pool_alloc(&cache->mem_pool, sizeof(*fse) + len + 1);
130133
/* init the rest of the structure */
131134
fsentry_init(fse, list, name, len);
132135
fse->next = NULL;
@@ -146,35 +149,29 @@ inline static void fsentry_addref(struct fsentry *fse)
146149
}
147150

148151
/*
149-
* Release the reference to an fsentry, frees the memory if its the last ref.
152+
* Release the reference to an fsentry.
150153
*/
151154
static void fsentry_release(struct fsentry *fse)
152155
{
153156
if (fse->list)
154157
fse = fse->list;
155158

156-
if (InterlockedDecrement(&(fse->u.refcnt)))
157-
return;
158-
159-
while (fse) {
160-
struct fsentry *next = fse->next;
161-
free(fse);
162-
fse = next;
163-
}
159+
InterlockedDecrement(&(fse->u.refcnt));
164160
}
165161

166162
/*
167163
* Allocate and initialize an fsentry from a WIN32_FIND_DATA structure.
168164
*/
169-
static struct fsentry *fseentry_create_entry(struct fsentry *list,
165+
static struct fsentry *fseentry_create_entry(struct fscache *cache,
166+
struct fsentry *list,
170167
const WIN32_FIND_DATAW *fdata)
171168
{
172169
char buf[MAX_PATH * 3];
173170
int len;
174171
struct fsentry *fse;
175172
len = xwcstoutf(buf, fdata->cFileName, ARRAY_SIZE(buf));
176173

177-
fse = fsentry_alloc(list, buf, len);
174+
fse = fsentry_alloc(cache, list, buf, len);
178175

179176
fse->st_mode = file_attr_to_st_mode(fdata->dwFileAttributes);
180177
fse->dirent.d_type = S_ISDIR(fse->st_mode) ? DT_DIR : DT_REG;
@@ -192,7 +189,7 @@ static struct fsentry *fseentry_create_entry(struct fsentry *list,
192189
* Dir should not contain trailing '/'. Use an empty string for the current
193190
* directory (not "."!).
194191
*/
195-
static struct fsentry *fsentry_create_list(const struct fsentry *dir,
192+
static struct fsentry *fsentry_create_list(struct fscache *cache, const struct fsentry *dir,
196193
int *dir_not_found)
197194
{
198195
wchar_t pattern[MAX_PATH + 2]; /* + 2 for '/' '*' */
@@ -231,14 +228,14 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
231228
}
232229

233230
/* allocate object to hold directory listing */
234-
list = fsentry_alloc(NULL, dir->dirent.d_name, dir->len);
231+
list = fsentry_alloc(cache, NULL, dir->dirent.d_name, dir->len);
235232
list->st_mode = S_IFDIR;
236233
list->dirent.d_type = DT_DIR;
237234

238235
/* walk directory and build linked list of fsentry structures */
239236
phead = &list->next;
240237
do {
241-
*phead = fseentry_create_entry(list, &fdata);
238+
*phead = fseentry_create_entry(cache, list, &fdata);
242239
phead = &(*phead)->next;
243240
} while (FindNextFileW(h, &fdata));
244241

@@ -250,7 +247,7 @@ static struct fsentry *fsentry_create_list(const struct fsentry *dir,
250247
if (err == ERROR_NO_MORE_FILES)
251248
return list;
252249

253-
/* otherwise free the list and return error */
250+
/* otherwise release the list and return error */
254251
fsentry_release(list);
255252
errno = err_win_to_posix(err);
256253
return NULL;
@@ -273,7 +270,9 @@ static void fscache_add(struct fscache *cache, struct fsentry *fse)
273270
*/
274271
static void fscache_clear(struct fscache *cache)
275272
{
276-
hashmap_clear_and_free(&cache->map, struct fsentry, ent);
273+
mem_pool_discard(&cache->mem_pool, 0);
274+
mem_pool_init(&cache->mem_pool, 0);
275+
hashmap_clear(&cache->map);
277276
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, 0);
278277
cache->lstat_requests = cache->opendir_requests = 0;
279278
cache->fscache_misses = cache->fscache_requests = 0;
@@ -326,7 +325,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
326325
}
327326

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

331330
/* leave on error (errno set by fsentry_create_list) */
332331
if (!fse) {
@@ -336,7 +335,7 @@ static struct fsentry *fscache_get(struct fscache *cache, struct fsentry *key)
336335
* empty, which for all practical matters is the same
337336
* thing as far as fscache is concerned).
338337
*/
339-
fse = fsentry_alloc(key->list->list,
338+
fse = fsentry_alloc(cache, key->list->list,
340339
key->list->dirent.d_name,
341340
key->list->len);
342341
fse->st_mode = 0;
@@ -415,6 +414,7 @@ int fscache_enable(size_t initial_size)
415414
* '4' was determined empirically by testing several repos
416415
*/
417416
hashmap_init(&cache->map, (hashmap_cmp_fn)fsentry_cmp, NULL, initial_size * 4);
417+
mem_pool_init(&cache->mem_pool, 0);
418418
if (!TlsSetValue(dwTlsIndex, cache))
419419
BUG("TlsSetValue error");
420420
}
@@ -446,7 +446,8 @@ void fscache_disable(void)
446446
"total requests/misses %u/%u\n",
447447
cache->lstat_requests, cache->opendir_requests,
448448
cache->fscache_requests, cache->fscache_misses);
449-
fscache_clear(cache);
449+
mem_pool_discard(&cache->mem_pool, 0);
450+
hashmap_clear(&cache->map);
450451
free(cache);
451452
}
452453

@@ -631,6 +632,8 @@ void fscache_merge(struct fscache *dest)
631632
while ((e = hashmap_iter_next(&iter)))
632633
hashmap_add(&dest->map, e);
633634

635+
mem_pool_combine(&dest->mem_pool, &cache->mem_pool);
636+
634637
dest->lstat_requests += cache->lstat_requests;
635638
dest->opendir_requests += cache->opendir_requests;
636639
dest->fscache_requests += cache->fscache_requests;

0 commit comments

Comments
 (0)