-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[memprof] Use BLAKE for FrameId #109501
[memprof] Use BLAKE for FrameId #109501
Conversation
This patch uses a stronger hash function for FrameId. Without this patch, I've observed hash collisions in fairly common scenarios. Specifically, for a given GUID, I see three pairs of hash collisions in the two-dimensional range 1 <= LineOffset <= 70 and 1 <= Column <= 50, which may be a bit too frequent. With the new function, I don't see collisions at all even for a large profile. Impact on serialization/deserialization should be as follows: - Up to indexed memprof format Version 2, inclusive: The FrameIds computed with the new hash function will show up as part of the profile file. However, the deserializer only treats FrameIds as keys (but not hash values) to retrieve Frames from the on-disk hash table, so a change of the hash function shouldn't matter. - For indexed memprof format Version 3, FrameIds do not show up at all in the resulting profile file. FrameIds are only used to break ties when we sort Frames in writeMemProfFrameArray.
@llvm/pr-subscribers-pgo Author: Kazu Hirata (kazutakahirata) ChangesThis patch uses a stronger hash function for FrameId. Without this patch, I've observed hash collisions in fairly common Impact on serialization/deserialization should be as follows:
Full diff: https://github.com/llvm/llvm-project/pull/109501.diff 1 Files Affected:
diff --git a/llvm/include/llvm/ProfileData/MemProf.h b/llvm/include/llvm/ProfileData/MemProf.h
index 892865a0a26fea..25e183ee4c1327 100644
--- a/llvm/include/llvm/ProfileData/MemProf.h
+++ b/llvm/include/llvm/ProfileData/MemProf.h
@@ -7,8 +7,10 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/ProfileData/MemProfData.inc"
+#include "llvm/Support/BLAKE3.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/EndianStream.h"
+#include "llvm/Support/HashBuilder.h"
#include "llvm/Support/raw_ostream.h"
#include <bitset>
@@ -312,20 +314,13 @@ struct Frame {
// hashing from llvm ADT since we are going to persist the hash id, the hash
// combine algorithm in ADT uses a new randomized seed each time.
inline FrameId hash() const {
- auto HashCombine = [](auto Value, size_t Seed) {
- std::hash<decltype(Value)> Hasher;
- // The constant used below is the 64 bit representation of the fractional
- // part of the golden ratio. Used here for the randomness in their bit
- // pattern.
- return Hasher(Value) + 0x9e3779b97f4a7c15 + (Seed << 6) + (Seed >> 2);
- };
-
- size_t Result = 0;
- Result ^= HashCombine(Function, Result);
- Result ^= HashCombine(LineOffset, Result);
- Result ^= HashCombine(Column, Result);
- Result ^= HashCombine(IsInlineFrame, Result);
- return static_cast<FrameId>(Result);
+ llvm::HashBuilder<llvm::TruncatedBLAKE3<8>, llvm::endianness::little>
+ HashBuilder;
+ HashBuilder.add(Function, LineOffset, Column, IsInlineFrame);
+ llvm::BLAKE3Result<8> Hash = HashBuilder.final();
+ FrameId Id;
+ std::memcpy(&Id, Hash.data(), sizeof(Hash));
+ return Id;
}
};
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the pointer @asl . Since the impact to runtime is minor, I'm fine with using Blake3. What do you think @kazutakahirata ?
I'm inclined to go ahead with this patch for now because:
In the longer term, I'm thinking about:
Note that once we remove the older memprof profile formats, |
This patch uses a stronger hash function for FrameId. Without this patch, I've observed hash collisions in fairly common scenarios. Specifically, for a given GUID, I see three pairs of hash collisions in the two-dimensional range 1 <= LineOffset <= 70 and 1 <= Column <= 50, which may be a bit too frequent. With the new function, I don't see collisions at all even for a large profile. Impact on serialization/deserialization should be as follows: - Up to indexed memprof format Version 2, inclusive: The FrameIds computed with the new hash function will show up as part of the profile file. However, the deserializer only treats FrameIds as keys (but not hash values) to retrieve Frames from the on-disk hash table, so a change of the hash function shouldn't matter. - For indexed memprof format Version 3, FrameIds do not show up at all in the resulting profile file. FrameIds are only used to break ties when we sort Frames in writeMemProfFrameArray.
This patch uses a stronger hash function for FrameId. Without this patch, I've observed hash collisions in fairly common scenarios. Specifically, for a given GUID, I see three pairs of hash collisions in the two-dimensional range 1 <= LineOffset <= 70 and 1 <= Column <= 50, which may be a bit too frequent. With the new function, I don't see collisions at all even for a large profile. Impact on serialization/deserialization should be as follows: - Up to indexed memprof format Version 2, inclusive: The FrameIds computed with the new hash function will show up as part of the profile file. However, the deserializer only treats FrameIds as keys (but not hash values) to retrieve Frames from the on-disk hash table, so a change of the hash function shouldn't matter. - For indexed memprof format Version 3, FrameIds do not show up at all in the resulting profile file. FrameIds are only used to break ties when we sort Frames in writeMemProfFrameArray.
This patch uses a stronger hash function for FrameId.
Without this patch, I've observed hash collisions in fairly common
scenarios. Specifically, for a given GUID, I see three pairs of hash
collisions in the two-dimensional range 1 <= LineOffset <= 70 and
1 <= Column <= 50, which may be a bit too frequent. With the new
function, I don't see collisions at all even for a large profile.
Impact on serialization/deserialization should be as follows:
Up to indexed memprof format Version 2, inclusive: The FrameIds
computed with the new hash function will show up as part of the
profile file. However, the deserializer only treats FrameIds as
keys (but not hash values) to retrieve Frames from the on-disk hash
table, so a change of the hash function shouldn't matter.
For indexed memprof format Version 3, FrameIds do not show up at all
in the resulting profile file. FrameIds are only used to break ties
when we sort Frames in writeMemProfFrameArray.