forked from OctaForge/libostd
hash chunk cache line boundary alignment optimization
parent
cc0fccb8cf
commit
0c297af0bd
|
@ -7,6 +7,7 @@
|
||||||
#define OSTD_INTERNAL_HASHTABLE_HH
|
#define OSTD_INTERNAL_HASHTABLE_HH
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include "ostd/types.hh"
|
#include "ostd/types.hh"
|
||||||
#include "ostd/utility.hh"
|
#include "ostd/utility.hh"
|
||||||
|
@ -120,6 +121,63 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
/* Use template metaprogramming to figure out a correct number
|
||||||
|
* of elements to use per chunk for proper cache alignment
|
||||||
|
* (i.e. sizeof(Chunk) % CACHE_LINE_SIZE == 0).
|
||||||
|
*
|
||||||
|
* If this is not possible, use the upper bound and pad the
|
||||||
|
* structure with some extra bytes.
|
||||||
|
*/
|
||||||
|
static constexpr Size CACHE_LINE_SIZE = 64;
|
||||||
|
static constexpr Size CHUNK_LOWER_BOUND = 32;
|
||||||
|
static constexpr Size CHUNK_UPPER_BOUND = 128;
|
||||||
|
|
||||||
|
template<typename E, Size N>
|
||||||
|
struct HashChainAlign {
|
||||||
|
static constexpr Size csize = sizeof(HashChain<E>[N]) + sizeof(void *);
|
||||||
|
static constexpr Size value = ((csize % CACHE_LINE_SIZE) == 0)
|
||||||
|
? N : HashChainAlign<E, N + 1>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename E>
|
||||||
|
struct HashChainAlign<E, CHUNK_UPPER_BOUND> {
|
||||||
|
static constexpr Size value = CHUNK_UPPER_BOUND;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Size N, bool B>
|
||||||
|
struct HashChainPad;
|
||||||
|
|
||||||
|
template<Size N>
|
||||||
|
struct HashChainPad<N, true> {};
|
||||||
|
|
||||||
|
template<Size N>
|
||||||
|
struct HashChainPad<N, false> {
|
||||||
|
byte pad[CACHE_LINE_SIZE - (N % CACHE_LINE_SIZE)];
|
||||||
|
};
|
||||||
|
|
||||||
|
template<Size N>
|
||||||
|
struct HashPad: HashChainPad<N, N % CACHE_LINE_SIZE == 0> {};
|
||||||
|
|
||||||
|
template<typename E, Size V = HashChainAlign<E, CHUNK_LOWER_BOUND>::value,
|
||||||
|
bool P = (V == CHUNK_UPPER_BOUND)
|
||||||
|
> struct HashChunk;
|
||||||
|
|
||||||
|
template<typename E, Size V>
|
||||||
|
struct HashChunk<E, V, false> {
|
||||||
|
static constexpr Size num = V;
|
||||||
|
HashChain<E> chains[num];
|
||||||
|
HashChunk *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename E, Size V>
|
||||||
|
struct HashChunk<E, V, true>: HashPad<
|
||||||
|
sizeof(HashChain<E>[V]) + sizeof(void *)
|
||||||
|
> {
|
||||||
|
static constexpr Size num = V;
|
||||||
|
HashChain<E> chains[num];
|
||||||
|
HashChunk *next;
|
||||||
|
};
|
||||||
|
|
||||||
template<
|
template<
|
||||||
typename B, /* contains methods specific to each ht type */
|
typename B, /* contains methods specific to each ht type */
|
||||||
typename E, /* element type */
|
typename E, /* element type */
|
||||||
|
@ -131,14 +189,8 @@ namespace detail {
|
||||||
bool Multihash
|
bool Multihash
|
||||||
> struct Hashtable {
|
> struct Hashtable {
|
||||||
private:
|
private:
|
||||||
static constexpr Size CHUNKSIZE = 64;
|
using Chain = HashChain<E>;
|
||||||
|
using Chunk = HashChunk<E>;
|
||||||
using Chain = detail::HashChain<E>;
|
|
||||||
|
|
||||||
struct Chunk {
|
|
||||||
Chain chains[CHUNKSIZE];
|
|
||||||
Chunk *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
Size p_size;
|
Size p_size;
|
||||||
Size p_len;
|
Size p_len;
|
||||||
|
@ -203,9 +255,9 @@ private:
|
||||||
allocator_construct(get_challoc(), chunk);
|
allocator_construct(get_challoc(), chunk);
|
||||||
chunk->next = p_chunks;
|
chunk->next = p_chunks;
|
||||||
p_chunks = chunk;
|
p_chunks = chunk;
|
||||||
for (Size i = 0; i < (CHUNKSIZE - 1); ++i)
|
for (Size i = 0; i < (Chunk::num - 1); ++i)
|
||||||
chunk->chains[i].next = &chunk->chains[i + 1];
|
chunk->chains[i].next = &chunk->chains[i + 1];
|
||||||
chunk->chains[CHUNKSIZE - 1].next = p_unused;
|
chunk->chains[Chunk::num - 1].next = p_unused;
|
||||||
p_unused = chunk->chains;
|
p_unused = chunk->chains;
|
||||||
}
|
}
|
||||||
++p_len;
|
++p_len;
|
||||||
|
|
Loading…
Reference in New Issue