mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-19 18:39:26 +00:00
Merge pull request #1498 from libgit2/vmg/atomic64
64 bit atomic operations and shared cache memory usage
This commit is contained in:
commit
7915e6cc66
@ -133,7 +133,8 @@ enum {
|
|||||||
GIT_OPT_SET_SEARCH_PATH,
|
GIT_OPT_SET_SEARCH_PATH,
|
||||||
GIT_OPT_SET_CACHE_OBJECT_LIMIT,
|
GIT_OPT_SET_CACHE_OBJECT_LIMIT,
|
||||||
GIT_OPT_SET_CACHE_MAX_SIZE,
|
GIT_OPT_SET_CACHE_MAX_SIZE,
|
||||||
GIT_OPT_ENABLE_CACHING
|
GIT_OPT_ENABLE_CACHING,
|
||||||
|
GIT_OPT_GET_CACHED_MEMORY
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
15
src/cache.c
15
src/cache.c
@ -18,7 +18,8 @@
|
|||||||
GIT__USE_OIDMAP
|
GIT__USE_OIDMAP
|
||||||
|
|
||||||
bool git_cache__enabled = true;
|
bool git_cache__enabled = true;
|
||||||
size_t git_cache__max_storage = (4 * 1024 * 1024);
|
int64_t git_cache__max_storage = (256 * 1024 * 1024);
|
||||||
|
git_atomic64 git_cache__current_storage = {0};
|
||||||
|
|
||||||
static size_t git_cache__max_object_size[8] = {
|
static size_t git_cache__max_object_size[8] = {
|
||||||
0, /* GIT_OBJ__EXT1 */
|
0, /* GIT_OBJ__EXT1 */
|
||||||
@ -81,6 +82,7 @@ static void clear_cache(git_cache *cache)
|
|||||||
});
|
});
|
||||||
|
|
||||||
kh_clear(oid, cache->map);
|
kh_clear(oid, cache->map);
|
||||||
|
git_atomic64_add(&git_cache__current_storage, -cache->used_memory);
|
||||||
cache->used_memory = 0;
|
cache->used_memory = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +108,7 @@ void git_cache_free(git_cache *cache)
|
|||||||
static void cache_evict_entries(git_cache *cache)
|
static void cache_evict_entries(git_cache *cache)
|
||||||
{
|
{
|
||||||
uint32_t seed = rand();
|
uint32_t seed = rand();
|
||||||
size_t evict_count = 8;
|
int64_t evicted_memory = 0, evict_count = 8;
|
||||||
|
|
||||||
/* do not infinite loop if there's not enough entries to evict */
|
/* do not infinite loop if there's not enough entries to evict */
|
||||||
if (evict_count > kh_size(cache->map)) {
|
if (evict_count > kh_size(cache->map)) {
|
||||||
@ -121,12 +123,15 @@ static void cache_evict_entries(git_cache *cache)
|
|||||||
git_cached_obj *evict = kh_val(cache->map, pos);
|
git_cached_obj *evict = kh_val(cache->map, pos);
|
||||||
|
|
||||||
evict_count--;
|
evict_count--;
|
||||||
cache->used_memory -= evict->size;
|
evicted_memory += evict->size;
|
||||||
git_cached_obj_decref(evict);
|
git_cached_obj_decref(evict);
|
||||||
|
|
||||||
kh_del(oid, cache->map, pos);
|
kh_del(oid, cache->map, pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cache->used_memory -= evicted_memory;
|
||||||
|
git_atomic64_add(&git_cache__current_storage, -evicted_memory);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool cache_should_store(git_otype object_type, size_t object_size)
|
static bool cache_should_store(git_otype object_type, size_t object_size)
|
||||||
@ -171,7 +176,8 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
|
|||||||
if (git_mutex_lock(&cache->lock) < 0)
|
if (git_mutex_lock(&cache->lock) < 0)
|
||||||
return entry;
|
return entry;
|
||||||
|
|
||||||
if (cache->used_memory > git_cache__max_storage)
|
/* soften the load on the cache */
|
||||||
|
if (git_cache__current_storage.val > git_cache__max_storage)
|
||||||
cache_evict_entries(cache);
|
cache_evict_entries(cache);
|
||||||
|
|
||||||
pos = kh_get(oid, cache->map, &entry->oid);
|
pos = kh_get(oid, cache->map, &entry->oid);
|
||||||
@ -186,6 +192,7 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry)
|
|||||||
kh_val(cache->map, pos) = entry;
|
kh_val(cache->map, pos) = entry;
|
||||||
git_cached_obj_incref(entry);
|
git_cached_obj_incref(entry);
|
||||||
cache->used_memory += entry->size;
|
cache->used_memory += entry->size;
|
||||||
|
git_atomic64_add(&git_cache__current_storage, (int64_t)entry->size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* found */
|
/* found */
|
||||||
|
@ -31,11 +31,12 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
git_oidmap *map;
|
git_oidmap *map;
|
||||||
git_mutex lock;
|
git_mutex lock;
|
||||||
size_t used_memory;
|
int64_t used_memory;
|
||||||
} git_cache;
|
} git_cache;
|
||||||
|
|
||||||
extern bool git_cache__enabled;
|
extern bool git_cache__enabled;
|
||||||
extern size_t git_cache__max_storage;
|
extern int64_t git_cache__max_storage;
|
||||||
|
extern git_atomic64 git_cache__current_storage;
|
||||||
|
|
||||||
int git_cache_set_max_object_size(git_otype type, size_t size);
|
int git_cache_set_max_object_size(git_otype type, size_t size);
|
||||||
|
|
||||||
|
@ -18,6 +18,14 @@ typedef struct {
|
|||||||
#endif
|
#endif
|
||||||
} git_atomic;
|
} git_atomic;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
#if defined(GIT_WIN32)
|
||||||
|
__int64 val;
|
||||||
|
#else
|
||||||
|
int64_t val;
|
||||||
|
#endif
|
||||||
|
} git_atomic64;
|
||||||
|
|
||||||
GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
|
GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
|
||||||
{
|
{
|
||||||
a->val = val;
|
a->val = val;
|
||||||
@ -57,6 +65,17 @@ GIT_INLINE(int) git_atomic_inc(git_atomic *a)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend)
|
||||||
|
{
|
||||||
|
#if defined(GIT_WIN32)
|
||||||
|
return _InterlockedExchangeAdd(&a->val, addend);
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
return __sync_add_and_fetch(&a->val, addend);
|
||||||
|
#else
|
||||||
|
# error "Unsupported architecture for atomic operations"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
GIT_INLINE(int) git_atomic_dec(git_atomic *a)
|
GIT_INLINE(int) git_atomic_dec(git_atomic *a)
|
||||||
{
|
{
|
||||||
#if defined(GIT_WIN32)
|
#if defined(GIT_WIN32)
|
||||||
@ -82,6 +101,17 @@ GIT_INLINE(void *) git___compare_and_swap(
|
|||||||
return (foundval == oldval) ? oldval : newval;
|
return (foundval == oldval) ? oldval : newval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GIT_INLINE(int) git_atomic64_add(git_atomic64 *a, int64_t addend)
|
||||||
|
{
|
||||||
|
#if defined(GIT_WIN32)
|
||||||
|
return _InterlockedExchangeAdd64(&a->val, addend);
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
return __sync_add_and_fetch(&a->val, addend);
|
||||||
|
#else
|
||||||
|
# error "Unsupported architecture for atomic operations"
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
#define git_thread unsigned int
|
#define git_thread unsigned int
|
||||||
@ -110,6 +140,12 @@ GIT_INLINE(int) git_atomic_inc(git_atomic *a)
|
|||||||
return ++a->val;
|
return ++a->val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend)
|
||||||
|
{
|
||||||
|
a->val += addend;
|
||||||
|
return a->val;
|
||||||
|
}
|
||||||
|
|
||||||
GIT_INLINE(int) git_atomic_dec(git_atomic *a)
|
GIT_INLINE(int) git_atomic_dec(git_atomic *a)
|
||||||
{
|
{
|
||||||
return --a->val;
|
return --a->val;
|
||||||
@ -125,6 +161,12 @@ GIT_INLINE(void *) git___compare_and_swap(
|
|||||||
return oldval;
|
return oldval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GIT_INLINE(int) git_atomic64_add(git_atomic64 *a, int64_t addend)
|
||||||
|
{
|
||||||
|
a->val += addend;
|
||||||
|
return a->val;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Atomically replace oldval with newval
|
/* Atomically replace oldval with newval
|
||||||
|
@ -39,7 +39,6 @@ int git_libgit2_capabilities()
|
|||||||
/* Declarations for tuneable settings */
|
/* Declarations for tuneable settings */
|
||||||
extern size_t git_mwindow__window_size;
|
extern size_t git_mwindow__window_size;
|
||||||
extern size_t git_mwindow__mapped_limit;
|
extern size_t git_mwindow__mapped_limit;
|
||||||
extern size_t git_odb__cache_size;
|
|
||||||
|
|
||||||
static int config_level_to_futils_dir(int config_level)
|
static int config_level_to_futils_dir(int config_level)
|
||||||
{
|
{
|
||||||
@ -104,12 +103,17 @@ int git_libgit2_opts(int key, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
case GIT_OPT_SET_CACHE_MAX_SIZE:
|
case GIT_OPT_SET_CACHE_MAX_SIZE:
|
||||||
git_cache__max_storage = va_arg(ap, size_t);
|
git_cache__max_storage = va_arg(ap, int64_t);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GIT_OPT_ENABLE_CACHING:
|
case GIT_OPT_ENABLE_CACHING:
|
||||||
git_cache__enabled = (va_arg(ap, int) != 0);
|
git_cache__enabled = (va_arg(ap, int) != 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GIT_OPT_GET_CACHED_MEMORY:
|
||||||
|
*(va_arg(ap, int64_t *)) = git_cache__current_storage.val;
|
||||||
|
*(va_arg(ap, int64_t *)) = git_cache__max_storage;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
Loading…
Reference in New Issue
Block a user