From: Derrick Stolee Date: Wed, 22 Aug 2018 11:14:42 GMT Subject: Re: [ANNOUNCE] Git v2.19.0-rc0 Message-ID: In-Reply-To: On 8/22/2018 3:39 AM, Ævar Arnfjörð Bjarmason wrote: > On Wed, Aug 22, 2018 at 8:20 AM Jeff King wrote: >> On Wed, Aug 22, 2018 at 05:36:26AM +0000, brian m. carlson wrote: >> >>> On Tue, Aug 21, 2018 at 11:03:44PM -0400, Jeff King wrote: >>> I don't know if something like this is an improvement or now, but this >>> seems to at least compile: >>> >>> diff --git a/cache.h b/cache.h >>> index 1398b2a4e4..3207f74771 100644 >>> --- a/cache.h >>> +++ b/cache.h >>> @@ -1033,7 +1033,13 @@ extern const struct object_id null_oid; >>> >>> static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2) >>> { >>> - return memcmp(sha1, sha2, the_hash_algo->rawsz); >>> + switch (the_hash_algo->rawsz) { >>> + case 20: >>> + case 32: >>> + return memcmp(sha1, sha2, the_hash_algo->rawsz); >>> + default: >>> + assert(0); >>> + } >> I think that would end up with the same slow code, as gcc would rather >> call memcmp than expand out the two sets of asm. >> >>> I won't have time to sit down and test this out until tomorrow afternoon >>> at the earliest. If you want to send in something in the mean time, >>> even if that limits things to just 20 for now, that's fine. >> I don't have a good option. The assert() thing works until I add in the >> "32" branch, but that's just punting the issue off until you add support >> for the new hash. >> >> Hand-rolling our own asm or C is a portability headache, and we need to >> change all of the callsites to use a new hasheq(). >> >> Hiding it behind a per-hash function is conceptually cleanest, but not >> quite as fast. And it also requires hasheq(). >> >> So all of the solutions seem non-trivial. Again, I'm starting to wonder >> if it's worth chasing this few percent. > Did you try __builtin_expect? It's a GCC builtin for these sorts of > situations, and sometimes helps: > https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html > > I.e. you'd tell GCC we expect to have the 20 there with: > > if (__builtin_expect(the_hash_algo->rawsz == 20, 1)) { ... } > > The perl codebase has LIKELY() and UNLIKELY() macros for this which if > the feature isn't available fall back on just plain C code: > https://github.com/Perl/perl5/blob/v5.27.7/perl.h#L3335-L3344 The other thing I was going to recommend (and I'll try to test this out myself later) is to see if 'the_hash_algo->rawsz' is being treated as a volatile variable, since it is being referenced through a pointer. Perhaps storing the value locally and then casing on it would help?