소스 검색

AK: Don't blindly use SipHash as default hash function

Although it has some interesting properties, SipHash is brutally slow
compared to our previous hash function. Since its introduction, it has
been highly visible in every profile of doing anything interesting with
LibJS or LibWeb.

By switching back, we gain a 10x speedup for 32-bit hashes, and "only"
a 3x speedup for 64-bit hashes.

This comes out to roughly 1.10x faster HashTable insertion, and roughly
2.25x faster HashTable lookup. Hashing is no longer at the top of
profiles and everything runs measurably faster.

For security-sensitive hash tables with user-controlled inputs, we can
opt into SipHash selectively on a case-by-case basis. The vast majority
of our uses don't fit that description though.
Andreas Kling 1 년 전
부모
커밋
2b8a920a7c
1개의 변경된 파일9개의 추가작업 그리고 4개의 파일을 삭제
  1. 9 4
      AK/Traits.h

+ 9 - 4
AK/Traits.h

@@ -10,7 +10,6 @@
 #include <AK/Concepts.h>
 #include <AK/Concepts.h>
 #include <AK/Forward.h>
 #include <AK/Forward.h>
 #include <AK/HashFunctions.h>
 #include <AK/HashFunctions.h>
-#include <AK/SipHash.h>
 #include <AK/StringHash.h>
 #include <AK/StringHash.h>
 
 
 namespace AK {
 namespace AK {
@@ -41,7 +40,10 @@ struct Traits<T> : public DefaultTraits<T> {
     static constexpr bool is_trivially_serializable() { return true; }
     static constexpr bool is_trivially_serializable() { return true; }
     static unsigned hash(T value)
     static unsigned hash(T value)
     {
     {
-        return standard_sip_hash(static_cast<u64>(value));
+        if constexpr (sizeof(T) < 8)
+            return int_hash(value);
+        else
+            return u64_hash(value);
     }
     }
 };
 };
 
 
@@ -52,14 +54,17 @@ struct Traits<T> : public DefaultTraits<T> {
     static constexpr bool is_trivially_serializable() { return true; }
     static constexpr bool is_trivially_serializable() { return true; }
     static unsigned hash(T value)
     static unsigned hash(T value)
     {
     {
-        return standard_sip_hash(bit_cast<u64>(static_cast<double>(value)));
+        if constexpr (sizeof(T) < 8)
+            return int_hash(bit_cast<u32>(value));
+        else
+            return u64_hash(bit_cast<u64>(value));
     }
     }
 };
 };
 #endif
 #endif
 
 
 template<typename T>
 template<typename T>
 requires(IsPointer<T> && !Detail::IsPointerOfType<char, T>) struct Traits<T> : public DefaultTraits<T> {
 requires(IsPointer<T> && !Detail::IsPointerOfType<char, T>) struct Traits<T> : public DefaultTraits<T> {
-    static unsigned hash(T p) { return standard_sip_hash(bit_cast<FlatPtr>(p)); }
+    static unsigned hash(T p) { return ptr_hash(bit_cast<FlatPtr>(p)); }
     static constexpr bool is_trivial() { return true; }
     static constexpr bool is_trivial() { return true; }
 };
 };