git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] packfile: skip decompressing and hashing blobs in add_promisor_object()

From
Aaron Plattner <aplattner@nvidia.com>
Date
Dec 5, 2025, 18:50 UTC
Message-ID
<235d80bd-2516-47f9-958f-0e5a16892758@nvidia.com>
In-Reply-To
<20251205180106.GC18566@coredump.intra.peff.net>
On 12/5/25 10:01 AM, Jeff King wrote:
Show 37 quoted lines
> On Fri, Dec 05, 2025 at 12:48:54PM -0500, Jeff King wrote:
> 
>> OK, so we are checking the type up front and then skipping
>> parse_object() if we can. But there is already some logic inside
>> parse_object() for these kinds of optimizations. If we tell it we are
>> not interested in checking the hash of the objects, then it knows it can
>> skip loading the blob entirely.
>>
>> But it can _also_ use that flag for other things, like using the
>> commit-graph rather than loading individual commit objects. So doing
>> this:
>>    
>> diff --git a/packfile.c b/packfile.c
>> index 9cc11b6dc5..01b992a4e1 100644
>> --- a/packfile.c
>> +++ b/packfile.c
>> @@ -2310,7 +2310,8 @@ static int add_promisor_object(const struct object_id *oid,
>>   		we_parsed_object = 0;
>>   	} else {
>>   		we_parsed_object = 1;
>> -		obj = parse_object(pack->repo, oid);
>> +		obj = parse_object_with_flags(pack->repo, oid,
>> +					      PARSE_OBJECT_SKIP_HASH_CHECK);
>>   	}
>>   
>>   	if (!obj)
>>
>> drops my linux.git case down to 49s. It's skipping the blobs (with no
>> need for your patch) and loading the commits out of the graph file. Note
>> that you may need to "git commit-graph write --reachable" to see the
>> effect (I think we do generate graphs by default in git-gc these days,
>> but I'm not sure if we do so right after cloning).
> 
> Oh, and obviously it is skipping the hash computation on the objects,
> too. That's probably not as important as avoiding the object loads in
> the first place, but it may also be making a measurable difference on
> the ones we do load (notably trees here).

Thanks! I had looked at PARSE_OBJECT_SKIP_HASH_CHECK but it wasn't obvious to me whether it could be used here or not.

Unfortunately, setting that flag doesn't seem to improve performance for me because in parse_object_with_flags(), lookup_object() returns an obj pointer with obj->parsed == 0 and obj->type == OBJ_NONE. So it skips this block and ends up inflating the object anyway:

	if ((!obj || obj->type == OBJ_BLOB) &&
	    odb_read_object_info(r->objects, oid, NULL) == OBJ_BLOB) {
		if (!skip_hash && stream_object_signature(r, repl) < 0) {
			error(_("hash mismatch %s"), oid_to_hex(oid));
			return NULL;
		}
		parse_blob_buffer(lookup_blob(r, oid));
		return lookup_object(r, oid);
	}

I was confused about why the check was structured that way, but reading the description of commit 8db2dad7a045e376b9c4f51ddd33da43c962e3a4 cleared that up. Thank you for thoroughly documenting that!

Are OBJ_NONE objects expected here? Should the check be
	if ((!obj || obj->type == OBJ_NONE || obj->type == OBJ_BLOB) &&
	    odb_read_object_info(r->objects, oid, NULL) == OBJ_BLOB) {
	    [...]
	}
?

If I make that change combined with your PARSE_OBJECT_SKIP_HASH_CHECK change then the time drops to 1:58, so that's great!

> -Peff
Previous: Jeff KingNext: Jeff King
Message 7 of 10 in “packfile: skip decompressing and hashing blobs in add_promisor_object()”
  1. packfile: skip decompressing and hashing blobs in add_promisor_object()Aaron Plattner, Dec 4, 2025
  2. Patrick SteinhardtDec 5, 2025
  3. Aaron PlattnerDec 5, 2025
  4. Jeff KingDec 5, 2025
  5. Jeff KingDec 5, 2025
  6. Jeff KingDec 5, 2025
  7. Aaron PlattnerDec 5, 2025
  8. Jeff KingDec 5, 2025
  9. Aaron PlattnerDec 5, 2025
  10. Jeff KingDec 6, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.