Browse Source

8 byte hashmap search optimization, fix gcc build

Kajetan Johannes Hammerle 2 weeks ago
parent
commit
81dc5194b8
3 changed files with 50 additions and 20 deletions
  1. 1 0
      CMakeLists.txt
  2. 24 20
      src/HashMap.c
  3. 25 0
      test/modules/HashMapTests.c

+ 1 - 0
CMakeLists.txt

@@ -128,3 +128,4 @@ target_compile_definitions(test PRIVATE ${DEFINITIONS})
 add_executable(performance ${SRC_PERFORMANCE})
 target_link_libraries(performance PRIVATE core)
 target_include_directories(performance PRIVATE include)
+target_compile_definitions(performance PRIVATE ${DEFINITIONS})

+ 24 - 20
src/HashMap.c

@@ -45,27 +45,30 @@ static size_t searchSlot(CoreHashMap* m, const void* key) {
     }
 }
 
-static void* searchValueU32(const CoreHashMap* m, const void* rawKey) {
-    u32 key = *(const u32*)rawKey;
-    if(m->capacity != 0) {
-        if(key == 0) {
-            size_t i = m->capacity - 1;
-            return ((u32*)m->keys)[i] == 0 ? getValue(m, i) : nullptr;
-        }
-        size_t baseHash = ((size_t)key) * 514685581u;
-        size_t end = m->capacity - 2;
-        for(size_t i = 0; i <= end; i++) {
-            size_t hash = (baseHash + i) & end;
-            u32 keyEntry = *(u32*)getKey(m, hash);
-            if(keyEntry == key) {
-                return getValue(m, hash);
-            } else if(keyEntry == 0) {
-                return nullptr;
-            }
-        }
+#define SEARCH_VALUE(type, Type)                                               \
+    static void* searchValue##Type(const CoreHashMap* m, const void* rawKey) { \
+        type key = *(const type*)rawKey;                                       \
+        if(m->capacity != 0) {                                                 \
+            if(key == 0) {                                                     \
+                size_t i = m->capacity - 1;                                    \
+                return ((type*)m->keys)[i] == 0 ? getValue(m, i) : nullptr;    \
+            }                                                                  \
+            size_t baseHash = ((size_t)key) * 514685581u;                      \
+            size_t end = m->capacity - 2;                                      \
+            for(size_t i = 0; i <= end; i++) {                                 \
+                size_t hash = (baseHash + i) & end;                            \
+                type keyEntry = *(type*)getKey(m, hash);                       \
+                if(keyEntry == key) {                                          \
+                    return getValue(m, hash);                                  \
+                } else if(keyEntry == 0) {                                     \
+                    return nullptr;                                            \
+                }                                                              \
+            }                                                                  \
+        }                                                                      \
+        return nullptr;                                                        \
     }
-    return nullptr;
-}
+SEARCH_VALUE(u32, U32)
+SEARCH_VALUE(u64, U64)
 
 static void* searchValue(const CoreHashMap* m, const void* key) {
     if(m->capacity != 0) {
@@ -102,6 +105,7 @@ CoreHashMap coreInitHashMap(size_t keySize, size_t valueSize, CoreHasher hasher,
     if(hasher == coreHash && equal == coreEqual) {
         switch(keySize) {
             case sizeof(u32): search = searchValueU32; break;
+            case sizeof(u64): search = searchValueU64; break;
         }
     }
     return (CoreHashMap){nullptr, nullptr, keySize, valueSize, 0,

+ 25 - 0
test/modules/HashMapTests.c

@@ -244,6 +244,30 @@ static void testSearchStruct() {
     coreDestroyHashMap(&map);
 }
 
+static void testSearchSize() {
+    CoreHashMap map =
+        CORE_HASH_MAP(sizeof(size_t), sizeof(int), coreHash, coreEqual);
+    CORE_TEST_NULL(coreHashMapSearch(&map, size_t, 0, int));
+    CORE_TEST_NULL(coreHashMapSearch(&map, size_t, 1, int));
+    CORE_TEST_NULL(coreHashMapSearch(&map, size_t, 2, int));
+    coreHashMapPut(&map, size_t, 1, int, 3);
+
+    int* ap = coreHashMapSearch(&map, size_t, 1, int);
+    if(CORE_TEST_NOT_NULL(ap)) {
+        CORE_TEST_INT(3, *ap);
+    }
+    CORE_TEST_NULL(coreHashMapSearch(&map, size_t, 0, int));
+    CORE_TEST_NULL(coreHashMapSearch(&map, size_t, 2, int));
+
+    coreHashMapPut(&map, size_t, 0, int, 4);
+    int* cp = coreHashMapSearch(&map, size_t, 0, int);
+    if(CORE_TEST_NOT_NULL(cp)) {
+        CORE_TEST_INT(4, *cp);
+    }
+
+    coreDestroyHashMap(&map);
+}
+
 void coreTestHashMap(bool light) {
     testAdd();
     testMultipleAdd();
@@ -260,4 +284,5 @@ void coreTestHashMap(bool light) {
     testRemove();
     testHash();
     testSearchStruct();
+    testSearchSize();
 }