Commit 6a9117f557fed0afe4007c5de5158e0ebd3a187f

Patrick Steinhardt 2018-12-01T10:18:42

cache: use iteration interface for cache eviction To relieve us from memory pressure, we may regularly call `cache_evict_entries` to remove some entries from it. Unfortunately, our cache does not support a least-recently-used mode or something similar, which is why we evict entries completeley at random right now. Thing is, this is only possible due to the map interfaces exposing the entry indices, and we intend to completely remove those to decouple map users from map implementations. As soon as that is done, we are unable to do this random eviction anymore. Convert this to make use of an iterator for now. Obviously, there is no random eviction possible like that anymore, but we'll always start by evicting from the beginning of the map. Due to hashing, one may hope that the selected buckets will be evicted at least in some way unpredictably. But more likely than not, this will not be the case. But let's see what happens and if any users complain about degraded performance. If so, we might come up with a different scheme than random removal, e.g. by using an LRU cache.

diff --git a/src/cache.c b/src/cache.c
index a790783..b0b56ba 100644
--- a/src/cache.c
+++ b/src/cache.c
@@ -115,8 +115,7 @@ void git_cache_free(git_cache *cache)
 /* Called with lock */
 static void cache_evict_entries(git_cache *cache)
 {
-	uint32_t seed = rand();
-	size_t evict_count = 8;
+	size_t evict_count = 8, i;
 	ssize_t evicted_memory = 0;
 
 	/* do not infinite loop if there's not enough entries to evict  */
@@ -125,18 +124,19 @@ static void cache_evict_entries(git_cache *cache)
 		return;
 	}
 
+	i = 0;
 	while (evict_count > 0) {
-		size_t pos = seed++ % git_oidmap_end(cache->map);
+		git_cached_obj *evict;
+		const git_oid *key;
 
-		if (git_oidmap_has_data(cache->map, pos)) {
-			git_cached_obj *evict = git_oidmap_value_at(cache->map, pos);
+		if (git_oidmap_iterate((void **) &evict, cache->map, &i, &key) == GIT_ITEROVER)
+			break;
 
-			evict_count--;
-			evicted_memory += evict->size;
-			git_cached_obj_decref(evict);
+		evict_count--;
+		evicted_memory += evict->size;
+		git_cached_obj_decref(evict);
 
-			git_oidmap_delete_at(cache->map, pos);
-		}
+		git_oidmap_delete(cache->map, key);
 	}
 
 	cache->used_memory -= evicted_memory;