Using murmurhash2 instead of fnv
Rafael EspĂndola via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 9 07:03:06 PDT 2016
One annoying property of fnv is that it does one multiplication per
byte. Murmurhash2 does 3 per every 8 bytes.
With the attached hack linking libxul.so goes from 7.496263743s to 6.661119354.
If there is no objections I will write a proper patch for it.
Cheers,
Rafael
-------------- next part --------------
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
index 7b197ce..0c63318 100644
--- a/ELF/OutputSections.cpp
+++ b/ELF/OutputSections.cpp
@@ -1693,16 +1693,58 @@ template <class ELFT> void BuildIdSection<ELFT>::writeTo(uint8_t *Buf) {
HashBuf = Buf + 16;
}
+uint64_t MurmurHash64A(const void *key, int len, uint64_t seed) {
+ const uint64_t m = 0xc6a4a7935bd1e995LLU;
+ const int r = 47;
+
+ uint64_t h = seed ^ (len * m);
+
+ const uint64_t *data = (const uint64_t *)key;
+ const uint64_t *end = data + (len / 8);
+
+ while (data != end) {
+ uint64_t k = *data++;
+
+ k *= m;
+ k ^= k >> r;
+ k *= m;
+
+ h ^= k;
+ h *= m;
+ }
+
+ const unsigned char *data2 = (const unsigned char *)data;
+ switch (len & 7) {
+ case 7:
+ h ^= uint64_t(data2[6]) << 48;
+ case 6:
+ h ^= uint64_t(data2[5]) << 40;
+ case 5:
+ h ^= uint64_t(data2[4]) << 32;
+ case 4:
+ h ^= uint64_t(data2[3]) << 24;
+ case 3:
+ h ^= uint64_t(data2[2]) << 16;
+ case 2:
+ h ^= uint64_t(data2[1]) << 8;
+ case 1:
+ h ^= uint64_t(data2[0]);
+ h *= m;
+ };
+
+ h ^= h >> r;
+ h *= m;
+ h ^= h >> r;
+
+ return h;
+}
+
template <class ELFT>
void BuildIdFnv1<ELFT>::writeBuildId(ArrayRef<uint8_t> Buf) {
const endianness E = ELFT::TargetEndianness;
// 64-bit FNV-1 hash
- uint64_t Hash = 0xcbf29ce484222325;
- for (uint8_t B : Buf) {
- Hash *= 0x100000001b3;
- Hash ^= B;
- }
+ uint64_t Hash = MurmurHash64A(Buf.data(), Buf.size(), 0);
write64<E>(this->HashBuf, Hash);
}
More information about the llvm-commits
mailing list