Skip to content

Commit 4de6562

Browse files
pks-tgitster
authored andcommitted
upload-pack: look up "want" lines via commit-graph
During packfile negotiation the client will send "want" and "want-ref" lines to the server to tell it which objects it is interested in. The server-side parses each of those and looks them up to see whether it actually has requested objects. This lookup is performed by calling `parse_object()` directly, which thus hits the object database. In the general case though most of the objects the client requests will be commits. We can thus try to look up the object via the commit-graph opportunistically, which is much faster than doing the same via the object database. Refactor parsing of both "want" and "want-ref" lines to do so. The following benchmark is executed in a repository with a huge number of references. It uses cached request from git-fetch(1) as input to git-upload-pack(1) that contains about 876,000 "want" lines: Benchmark 1: HEAD~ Time (mean ± σ): 7.113 s ± 0.028 s [User: 6.900 s, System: 0.662 s] Range (min … max): 7.072 s … 7.168 s 10 runs Benchmark 2: HEAD Time (mean ± σ): 6.622 s ± 0.061 s [User: 6.452 s, System: 0.650 s] Range (min … max): 6.535 s … 6.727 s 10 runs Summary 'HEAD' ran 1.07 ± 0.01 times faster than 'HEAD~' Signed-off-by: Patrick Steinhardt <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 3436340 commit 4de6562

File tree

1 file changed

+17
-3
lines changed

1 file changed

+17
-3
lines changed

upload-pack.c

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1400,13 +1400,19 @@ static int parse_want(struct packet_writer *writer, const char *line,
14001400
const char *arg;
14011401
if (skip_prefix(line, "want ", &arg)) {
14021402
struct object_id oid;
1403+
struct commit *commit;
14031404
struct object *o;
14041405

14051406
if (get_oid_hex(arg, &oid))
14061407
die("git upload-pack: protocol error, "
14071408
"expected to get oid, not '%s'", line);
14081409

1409-
o = parse_object(the_repository, &oid);
1410+
commit = lookup_commit_in_graph(the_repository, &oid);
1411+
if (commit)
1412+
o = &commit->object;
1413+
else
1414+
o = parse_object(the_repository, &oid);
1415+
14101416
if (!o) {
14111417
packet_writer_error(writer,
14121418
"upload-pack: not our ref %s",
@@ -1434,7 +1440,7 @@ static int parse_want_ref(struct packet_writer *writer, const char *line,
14341440
if (skip_prefix(line, "want-ref ", &refname_nons)) {
14351441
struct object_id oid;
14361442
struct string_list_item *item;
1437-
struct object *o;
1443+
struct object *o = NULL;
14381444
struct strbuf refname = STRBUF_INIT;
14391445

14401446
strbuf_addf(&refname, "%s%s", get_git_namespace(), refname_nons);
@@ -1448,7 +1454,15 @@ static int parse_want_ref(struct packet_writer *writer, const char *line,
14481454
item = string_list_append(wanted_refs, refname_nons);
14491455
item->util = oiddup(&oid);
14501456

1451-
o = parse_object_or_die(&oid, refname_nons);
1457+
if (!starts_with(refname_nons, "refs/tags/")) {
1458+
struct commit *commit = lookup_commit_in_graph(the_repository, &oid);
1459+
if (commit)
1460+
o = &commit->object;
1461+
}
1462+
1463+
if (!o)
1464+
o = parse_object_or_die(&oid, refname_nons);
1465+
14521466
if (!(o->flags & WANTED)) {
14531467
o->flags |= WANTED;
14541468
add_object_array(o, NULL, want_obj);

0 commit comments

Comments
 (0)