Am 12.11.2018 um 15:54 schrieb Jeff King: > diff --git a/sha1-file.c b/sha1-file.c > index 4aae716a37..e53da0b701 100644 > --- a/sha1-file.c > +++ b/sha1-file.c > @@ -921,6 +921,24 @@ static int open_sha1_file(struct repository *r, > return -1; > } > > +static int quick_has_loose(struct repository *r, > + const unsigned char *sha1) > +{ > + int subdir_nr = sha1[0]; > + struct object_id oid; > + struct object_directory *odb; > + > + hashcpy(oid.hash, sha1); > + > + prepare_alt_odb(r); > + for (odb = r->objects->odb; odb; odb = odb->next) { > + odb_load_loose_cache(odb, subdir_nr); Is this thread-safe? What happens if e.g. one index-pack thread resizes the array while another one sorts it? Loading the cache explicitly up-front would avoid that, and improves performance a bit in my (very limited) tests on an SSD. Demo patch for next at the bottom. How does it do against your test cases? > + if (oid_array_lookup(&odb->loose_objects_cache, &oid) >= 0) > + return 1; > + } > + return 0; > +} > + > /* > * Map the loose object at "path" if it is not NULL, or the path found by > * searching for a loose object named "sha1". > @@ -1171,6 +1189,8 @@ static int sha1_loose_object_info(struct repository *r, > if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) { > const char *path; > struct stat st; > + if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK)) > + return quick_has_loose(r, sha1) ? 0 : -1; > if (stat_sha1_file(r, sha1, &st, &path) < 0) > return -1; > if (oi->disk_sizep) > builtin/fetch.c | 2 ++ builtin/index-pack.c | 2 ++ fetch-pack.c | 2 ++ object-store.h | 1 + sha1-file.c | 30 +++++++++++++++++++++++++++--- 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/builtin/fetch.c b/builtin/fetch.c index e0140327aa..4b031f5da5 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -301,6 +301,8 @@ static void find_non_local_tags(const struct ref *refs, refname_hash_init(&existing_refs); refname_hash_init(&remote_refs); + repo_load_loose_cache(the_repository); + for_each_ref(add_one_refname, &existing_refs); for (ref = refs; ref; ref = ref->next) { if (!starts_with(ref->name, "refs/tags/")) diff --git a/builtin/index-pack.c b/builtin/index-pack.c index ac1f4ea9a7..7fc6321c77 100644 --- a/builtin/index-pack.c +++ b/builtin/index-pack.c @@ -1772,6 +1772,8 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix) if (show_stat) obj_stat = xcalloc(st_add(nr_objects, 1), sizeof(struct object_stat)); ofs_deltas = xcalloc(nr_objects, sizeof(struct ofs_delta_entry)); + if (startup_info->have_repository) + repo_load_loose_cache(the_repository); parse_pack_objects(pack_hash); if (report_end_of_input) write_in_full(2, "\0", 1); diff --git a/fetch-pack.c b/fetch-pack.c index dd6700bda9..96c4624d9e 100644 --- a/fetch-pack.c +++ b/fetch-pack.c @@ -656,6 +656,8 @@ static void mark_complete_and_common_ref(struct fetch_negotiator *negotiator, save_commit_buffer = 0; + repo_load_loose_cache(the_repository); + for (ref = *refs; ref; ref = ref->next) { struct object *o; diff --git a/object-store.h b/object-store.h index 8dceed0f31..f98dd3c857 100644 --- a/object-store.h +++ b/object-store.h @@ -53,6 +53,7 @@ void add_to_alternates_memory(const char *dir); * from 0 to 255 inclusive). */ void odb_load_loose_cache(struct object_directory *odb, int subdir_nr); +void repo_load_loose_cache(struct repository *r); struct packed_git { struct packed_git *next; diff --git a/sha1-file.c b/sha1-file.c index 05f63dfd4e..ae12f0a198 100644 --- a/sha1-file.c +++ b/sha1-file.c @@ -921,10 +921,19 @@ static int open_sha1_file(struct repository *r, return -1; } +static int quick_has_loose_odb(struct object_directory *odb, + const struct object_id *oid) +{ + int subdir_nr = oid->hash[0]; + + if (odb->loose_objects_subdir_seen[subdir_nr]) + return oid_array_lookup(&odb->loose_objects_cache, oid) >= 0; + return check_and_freshen_odb(odb, oid, 0); +} + static int quick_has_loose(struct repository *r, const unsigned char *sha1) { - int subdir_nr = sha1[0]; struct object_id oid; struct object_directory *odb; @@ -932,8 +941,7 @@ static int quick_has_loose(struct repository *r, prepare_alt_odb(r); for (odb = r->objects->odb; odb; odb = odb->next) { - odb_load_loose_cache(odb, subdir_nr); - if (oid_array_lookup(&odb->loose_objects_cache, &oid) >= 0) + if (quick_has_loose_odb(odb, &oid)) return 1; } return 0; @@ -2178,6 +2186,22 @@ void odb_load_loose_cache(struct object_directory *odb, int subdir_nr) strbuf_release(&buf); } +void repo_load_loose_cache(struct repository *r) +{ + struct object_directory *odb; + + prepare_alt_odb(r); + for (odb = r->objects->odb; odb; odb = odb->next) { + int i; + + for (i = 0; i < ARRAY_SIZE(odb->loose_objects_subdir_seen); i++) + odb_load_loose_cache(odb, i); + + /* Sort as a side-effect, only read the cache from here on. */ + oid_array_lookup(&odb->loose_objects_cache, &null_oid); + } +} + static int check_stream_sha1(git_zstream *stream, const char *hdr, unsigned long size,