commit 7bb0daa1028563181fe482524973f2a801da9261 from: Stefan Sperling date: Thu Jun 21 23:53:06 2018 UTC add a very simple object cache commit - 835e0dbdc83dcd863487243b581bdb1055f50855 commit + 7bb0daa1028563181fe482524973f2a801da9261 blob - 37a0ffc06e205900a148c1e549b6fffdc28b580e blob + ed4dac1b48bc84f3f2eae84ae0ab8cdfaeee3c59 --- lib/got_lib_object.h +++ lib/got_lib_object.h @@ -31,6 +31,7 @@ struct got_object { char *path_packfile; /* if packed */ off_t pack_offset; /* if packed */ struct got_delta_chain deltas; /* if deltified */ + int refcnt; /* > 0 if open and/or cached */ }; struct got_blob_object { blob - 3a9c223be1d3414bc6e7fb4f23b22fd12686d95d blob + b6db6c4cf6bcf528729664f7257826ed6a72156c --- lib/got_lib_repository.h +++ lib/got_lib_repository.h @@ -17,6 +17,14 @@ #define GOT_PACKIDX_CACHE_SIZE 64 #define GOT_PACK_CACHE_SIZE GOT_PACKIDX_CACHE_SIZE +#define GOT_OBJECT_CACHE_SIZE 8192 + +struct got_objcache_entry { + SIMPLEQ_ENTRY(got_objcache_entry) entry; + struct got_object_id id; + struct got_object *obj; +}; + struct got_repository { char *path; char *path_git_dir; @@ -26,4 +34,15 @@ struct got_repository { /* Open file handles for pack files. */ struct got_pack packs[GOT_PACK_CACHE_SIZE]; + + SIMPLEQ_HEAD(, got_objcache_entry) objcache; + int ncached; + int cache_hit; + int cache_miss; }; + +const struct got_error* +got_repo_cache_object(struct got_repository *, struct got_object_id *, + struct got_object *); +struct got_object *got_repo_get_cached_object(struct got_repository *, + struct got_object_id *); blob - 92f261b77ad672726166be16ae6a9c236961006e blob + 7fb951947c95f4ddf2f4abdfc5f7cd461226ea3f --- lib/object.c +++ lib/object.c @@ -46,6 +46,7 @@ #include "got_lib_zbuf.h" #include "got_lib_object.h" #include "got_lib_privsep.h" +#include "got_lib_repository.h" #ifndef MIN #define MIN(_a,_b) ((_a) < (_b) ? (_a) : (_b)) @@ -364,6 +365,12 @@ got_object_open(struct got_object **obj, struct got_re const struct got_error *err = NULL; char *path; int fd; + + *obj = got_repo_get_cached_object(repo, id); + if (*obj != NULL) { + (*obj)->refcnt++; + return NULL; + } err = object_path(&path, id, repo); if (err) @@ -386,6 +393,11 @@ got_object_open(struct got_object **obj, struct got_re goto done; memcpy((*obj)->id.sha1, id->sha1, SHA1_DIGEST_LENGTH); } + + if (err == NULL) { + (*obj)->refcnt++; + err = got_repo_cache_object(repo, id, *obj); + } done: free(path); if (fd != -1) @@ -409,6 +421,11 @@ got_object_open_by_id_str(struct got_object **obj, str void got_object_close(struct got_object *obj) { + if (obj->refcnt > 0) { + obj->refcnt--; + return; + } + if (obj->flags & GOT_OBJ_FLAG_DELTIFIED) { struct got_delta *delta; while (!SIMPLEQ_EMPTY(&obj->deltas.entries)) { @@ -1508,9 +1525,11 @@ got_object_open_by_path(struct got_object **obj, struc } } - if (te) + if (te) { err = got_object_open(obj, repo, te->id); - else + if (err) + goto done; + } else err = got_error(GOT_ERR_NO_OBJ); done: free(s0); blob - fa438dbb0d40c4058f0a9906b50419ccf3d738b8 blob + bc4db374f5b9d527fbfd2db70ef9d4a4adc82132 --- lib/repository.c +++ lib/repository.c @@ -28,6 +28,7 @@ #include "got_reference.h" #include "got_repository.h" #include "got_worktree.h" +#include "got_object.h" #include "got_lib_path.h" #include "got_lib_delta.h" @@ -147,6 +148,47 @@ done: } +const struct got_error* +got_repo_cache_object(struct got_repository *repo, struct got_object_id *id, + struct got_object *obj) +{ + struct got_objcache_entry *ce; + + if (repo->ncached >= GOT_OBJECT_CACHE_SIZE) { + ce = SIMPLEQ_FIRST(&repo->objcache); + SIMPLEQ_REMOVE_HEAD(&repo->objcache, entry); + got_object_close(ce->obj); + free(ce); + repo->ncached--; + } + + ce = calloc(1, sizeof(*ce)); + if (ce == NULL) + return got_error_from_errno(); + memcpy(&ce->id, id, sizeof(ce->id)); + ce->obj = obj; + obj->refcnt++; + SIMPLEQ_INSERT_HEAD(&repo->objcache, ce, entry); + repo->ncached++; + return NULL; +} + +struct got_object * +got_repo_get_cached_object(struct got_repository *repo, + struct got_object_id *id) +{ + struct got_objcache_entry *ce; + + SIMPLEQ_FOREACH(ce, &repo->objcache, entry) { + if (got_object_id_cmp(&ce->id, id) != 0) + continue; + repo->cache_hit++; + return ce->obj; + } + repo->cache_miss++; + return NULL; +} + const struct got_error * got_repo_open(struct got_repository **ret, const char *path) { @@ -238,6 +280,15 @@ got_repo_close(struct got_repository *repo) got_pack_close(&repo->packs[i]); } + while (!SIMPLEQ_EMPTY(&repo->objcache)) { + struct got_objcache_entry *ce; + ce = SIMPLEQ_FIRST(&repo->objcache); + SIMPLEQ_REMOVE_HEAD(&repo->objcache, entry); + got_object_close(ce->obj); + free(ce); + } + fprintf(stderr, "repo cache size: %d hit: %d miss: %d\n", repo->ncached, repo->cache_hit, repo->cache_miss); + free(repo->path); free(repo->path_git_dir); free(repo);