diff --git a/aeron-client/src/main/c/CMakeLists.txt b/aeron-client/src/main/c/CMakeLists.txt index 076732fbb6..5125e71bfc 100644 --- a/aeron-client/src/main/c/CMakeLists.txt +++ b/aeron-client/src/main/c/CMakeLists.txt @@ -41,6 +41,7 @@ endif () set(SOURCE collections/aeron_array_to_ptr_hash_map.c collections/aeron_bit_set.c + collections/aeron_hashing.c collections/aeron_int64_counter_map.c collections/aeron_int64_to_ptr_hash_map.c collections/aeron_int64_to_tagged_ptr_hash_map.c @@ -103,6 +104,7 @@ set(SOURCE set(HEADERS collections/aeron_array_to_ptr_hash_map.h collections/aeron_bit_set.h + collections/aeron_hashing.h collections/aeron_int64_counter_map.h collections/aeron_int64_to_ptr_hash_map.h collections/aeron_int64_to_tagged_ptr_hash_map.h diff --git a/aeron-client/src/main/c/collections/aeron_array_to_ptr_hash_map.h b/aeron-client/src/main/c/collections/aeron_array_to_ptr_hash_map.h index 9bbbf52e59..cff196095e 100644 --- a/aeron-client/src/main/c/collections/aeron_array_to_ptr_hash_map.h +++ b/aeron-client/src/main/c/collections/aeron_array_to_ptr_hash_map.h @@ -24,6 +24,7 @@ #include "util/aeron_bitutil.h" #include "util/aeron_strutil.h" #include "util/aeron_error.h" +#include "collections/aeron_hashing.h" #include "collections/aeron_map.h" #include "aeron_alloc.h" @@ -54,9 +55,9 @@ inline uint64_t aeron_array_hash(const uint8_t *arr, size_t length) return aeron_fnv_64a_buf((uint8_t *)arr, length); } -inline size_t aeron_array_to_ptr_hash_map_hash_key(uint64_t key, size_t mask) +inline size_t aeron_array_to_ptr_hash_map_hash_key(uint64_t key_hash_code, size_t mask) { - return (size_t)((key * 31) & mask); + return aeron_hash(key_hash_code, mask); } inline bool aeron_array_to_ptr_hash_map_compare( diff --git a/aeron-client/src/main/c/collections/aeron_bit_set.c b/aeron-client/src/main/c/collections/aeron_bit_set.c index 4b589e70c5..a62f17d75e 100644 --- a/aeron-client/src/main/c/collections/aeron_bit_set.c +++ b/aeron-client/src/main/c/collections/aeron_bit_set.c @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "aeron_bit_set.h" +#include "collections/aeron_bit_set.h" extern int aeron_bit_set_stack_alloc( size_t bit_set_length, uint64_t *static_array, size_t static_array_len, aeron_bit_set_t *bit_set); diff --git a/aeron-client/src/main/c/collections/aeron_hashing.c b/aeron-client/src/main/c/collections/aeron_hashing.c new file mode 100644 index 0000000000..124c618b2f --- /dev/null +++ b/aeron-client/src/main/c/collections/aeron_hashing.c @@ -0,0 +1,23 @@ +/* + * Copyright 2014-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "collections/aeron_hashing.h" + +extern uint32_t aeron_hash_code(uint64_t value); + +extern size_t aeron_hash(uint64_t value, size_t mask); + +extern size_t aeron_even_hash(uint64_t value, size_t mask); diff --git a/aeron-client/src/main/c/collections/aeron_hashing.h b/aeron-client/src/main/c/collections/aeron_hashing.h new file mode 100644 index 0000000000..6185ff4aef --- /dev/null +++ b/aeron-client/src/main/c/collections/aeron_hashing.h @@ -0,0 +1,47 @@ +/* + * Copyright 2014-2021 Real Logic Limited. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AERON_HASHING_H +#define AERON_HASHING_H + +#include +#include + +inline uint32_t aeron_hash_code(uint64_t value) +{ + uint64_t x = value; + + x = (x ^ (x >> 30u)) * UINT64_C(0xbf58476d1ce4e5b9); + x = (x ^ (x >> 27u)) * UINT64_C(0x94d049bb133111eb); + x = x ^ (x >> 31u); + + return (uint32_t)x ^ (uint32_t)(x >> 32u); +} + +inline size_t aeron_hash(uint64_t value, size_t mask) +{ + uint32_t hash = aeron_hash_code(value); + return (size_t)(hash & mask); +} + +inline size_t aeron_even_hash(uint64_t value, size_t mask) +{ + uint32_t hash = aeron_hash_code(value); + hash = (hash << 1u) - (hash << 8u); + return (size_t)(hash & mask); +} + +#endif //AERON_HASHING_H diff --git a/aeron-client/src/main/c/collections/aeron_int64_counter_map.c b/aeron-client/src/main/c/collections/aeron_int64_counter_map.c index b5292edd53..d5f9fe14e7 100644 --- a/aeron-client/src/main/c/collections/aeron_int64_counter_map.c +++ b/aeron-client/src/main/c/collections/aeron_int64_counter_map.c @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "aeron_int64_counter_map.h" +#include "collections/aeron_int64_counter_map.h" extern size_t aeron_int64_counter_map_hash_key(int64_t key, size_t mask); diff --git a/aeron-client/src/main/c/collections/aeron_int64_counter_map.h b/aeron-client/src/main/c/collections/aeron_int64_counter_map.h index bd18fb6c31..52ce61c0c9 100644 --- a/aeron-client/src/main/c/collections/aeron_int64_counter_map.h +++ b/aeron-client/src/main/c/collections/aeron_int64_counter_map.h @@ -22,6 +22,7 @@ #include "util/aeron_platform.h" #include "util/aeron_bitutil.h" +#include "collections/aeron_hashing.h" #include "collections/aeron_map.h" #include "aeron_alloc.h" @@ -38,9 +39,7 @@ aeron_int64_counter_map_t; inline size_t aeron_int64_counter_map_hash_key(int64_t key, size_t mask) { - uint64_t hash = ((uint64_t)key << UINT64_C(1)) - ((uint64_t)key << UINT64_C(8)); - - return (size_t)(hash & mask); + return aeron_even_hash((uint64_t)key, mask); } inline int aeron_int64_counter_map_init( @@ -78,7 +77,6 @@ inline void aeron_int64_counter_map_delete(aeron_int64_counter_map_t *map) inline int aeron_int64_counter_map_rehash(aeron_int64_counter_map_t *map, size_t new_entries_length) { size_t mask = new_entries_length - 1; - map->resize_threshold = (size_t)((new_entries_length / 2) * map->load_factor); int64_t *tmp_entries; @@ -114,6 +112,7 @@ inline int aeron_int64_counter_map_rehash(aeron_int64_counter_map_t *map, size_t map->entries = tmp_entries; map->entries_length = new_entries_length; + map->resize_threshold = (size_t)((new_entries_length / 2) * map->load_factor); return 0; } diff --git a/aeron-client/src/main/c/collections/aeron_int64_to_ptr_hash_map.h b/aeron-client/src/main/c/collections/aeron_int64_to_ptr_hash_map.h index 1ed2fdc1fd..17acf2f9db 100644 --- a/aeron-client/src/main/c/collections/aeron_int64_to_ptr_hash_map.h +++ b/aeron-client/src/main/c/collections/aeron_int64_to_ptr_hash_map.h @@ -22,6 +22,7 @@ #include "util/aeron_platform.h" #include "util/aeron_bitutil.h" #include "util/aeron_error.h" +#include "collections/aeron_hashing.h" #include "collections/aeron_map.h" #include "aeron_alloc.h" @@ -38,7 +39,7 @@ aeron_int64_to_ptr_hash_map_t; inline size_t aeron_int64_to_ptr_hash_map_hash_key(int64_t key, size_t mask) { - return (size_t)(((uint64_t)key * 31u) & mask); + return aeron_hash((uint64_t)key, mask); } inline int aeron_int64_to_ptr_hash_map_init( diff --git a/aeron-client/src/main/c/collections/aeron_int64_to_tagged_ptr_hash_map.h b/aeron-client/src/main/c/collections/aeron_int64_to_tagged_ptr_hash_map.h index 886964b3aa..bb36a1ce9d 100644 --- a/aeron-client/src/main/c/collections/aeron_int64_to_tagged_ptr_hash_map.h +++ b/aeron-client/src/main/c/collections/aeron_int64_to_tagged_ptr_hash_map.h @@ -23,6 +23,7 @@ #include "util/aeron_platform.h" #include "util/aeron_bitutil.h" +#include "collections/aeron_hashing.h" #include "collections/aeron_map.h" #include "aeron_alloc.h" @@ -50,7 +51,7 @@ aeron_int64_to_tagged_ptr_hash_map_t; inline size_t aeron_int64_to_tagged_ptr_hash_map_hash_key(int64_t key, size_t mask) { - return (size_t)(((uint64_t)key * 31u) & mask); + return aeron_hash((uint64_t)key, mask); } inline int aeron_int64_to_tagged_ptr_hash_map_init( diff --git a/aeron-client/src/main/c/collections/aeron_map.h b/aeron-client/src/main/c/collections/aeron_map.h index e0f1f0bb75..8d7f90c641 100644 --- a/aeron-client/src/main/c/collections/aeron_map.h +++ b/aeron-client/src/main/c/collections/aeron_map.h @@ -17,7 +17,7 @@ #ifndef AERON_AERON_MAP_H #define AERON_AERON_MAP_H -#define AERON_MAP_DEFAULT_LOAD_FACTOR (0.55f) +#define AERON_MAP_DEFAULT_LOAD_FACTOR (0.65f) #include diff --git a/aeron-client/src/main/c/collections/aeron_str_to_ptr_hash_map.h b/aeron-client/src/main/c/collections/aeron_str_to_ptr_hash_map.h index f56017cc36..bb20620da4 100644 --- a/aeron-client/src/main/c/collections/aeron_str_to_ptr_hash_map.h +++ b/aeron-client/src/main/c/collections/aeron_str_to_ptr_hash_map.h @@ -24,6 +24,7 @@ #include "util/aeron_bitutil.h" #include "util/aeron_strutil.h" #include "util/aeron_error.h" +#include "collections/aeron_hashing.h" #include "collections/aeron_map.h" #include "aeron_alloc.h" @@ -46,9 +47,9 @@ typedef struct aeron_str_to_ptr_hash_map_stct } aeron_str_to_ptr_hash_map_t; -inline size_t aeron_str_to_ptr_hash_map_hash_key(uint64_t key, size_t mask) +inline size_t aeron_str_to_ptr_hash_map_hash_key(uint64_t key_hash_code, size_t mask) { - return (size_t)((key * 31) & mask); + return aeron_hash(key_hash_code, mask); } inline bool aeron_str_to_ptr_hash_map_compare( diff --git a/aeron-client/src/main/c/util/aeron_bitutil.c b/aeron-client/src/main/c/util/aeron_bitutil.c index a191c65199..7cecc62b5c 100644 --- a/aeron-client/src/main/c/util/aeron_bitutil.c +++ b/aeron-client/src/main/c/util/aeron_bitutil.c @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "aeron_bitutil.h" +#include "util/aeron_bitutil.h" extern uint8_t *aeron_cache_line_align_buffer(uint8_t *buffer); extern int aeron_number_of_trailing_zeroes(int32_t value); diff --git a/aeron-client/src/main/c/util/aeron_dlopen.c b/aeron-client/src/main/c/util/aeron_dlopen.c index f7c814fe9c..7e5a9be5e8 100644 --- a/aeron-client/src/main/c/util/aeron_dlopen.c +++ b/aeron-client/src/main/c/util/aeron_dlopen.c @@ -24,9 +24,9 @@ #include #include -#include "aeron_dlopen.h" -#include "aeron_error.h" -#include "aeron_strutil.h" +#include "util/aeron_dlopen.h" +#include "util/aeron_error.h" +#include "util/aeron_strutil.h" #include "aeron_alloc.h" #if defined(AERON_COMPILER_GCC) diff --git a/aeron-client/src/test/c/collections/aeron_int64_counter_map_test.cpp b/aeron-client/src/test/c/collections/aeron_int64_counter_map_test.cpp index d9998d8021..69986aba14 100755 --- a/aeron-client/src/test/c/collections/aeron_int64_counter_map_test.cpp +++ b/aeron-client/src/test/c/collections/aeron_int64_counter_map_test.cpp @@ -112,6 +112,7 @@ TEST_F(Int64CounterMapTest, shouldGrowWhenThresholdExceeded) for (int64_t i = 0; i < 16; i++) { EXPECT_EQ(aeron_int64_counter_map_put(&m_map, i, value, nullptr), 0); + EXPECT_EQ(aeron_int64_counter_map_get(&m_map, i), value); } EXPECT_EQ(m_map.resize_threshold, 16u); diff --git a/aeron-driver/src/main/c/CMakeLists.txt b/aeron-driver/src/main/c/CMakeLists.txt index bea55c53e7..43182e393c 100644 --- a/aeron-driver/src/main/c/CMakeLists.txt +++ b/aeron-driver/src/main/c/CMakeLists.txt @@ -115,6 +115,7 @@ endif () SET(C_CLIENT_SOURCE ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_array_to_ptr_hash_map.c ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_bit_set.c + ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_hashing.c ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_int64_counter_map.c ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_int64_to_ptr_hash_map.c ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_int64_to_tagged_ptr_hash_map.c @@ -177,6 +178,7 @@ SET(C_CLIENT_SOURCE set(C_CLIENT_HEADERS ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_array_to_ptr_hash_map.h ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_bit_set.h + ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_hashing.h ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_int64_counter_map.h ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_int64_to_ptr_hash_map.h ${AERON_C_CLIENT_SOURCE_PATH}/collections/aeron_int64_to_tagged_ptr_hash_map.h