From 0c297af0bd1ec413fe9cc0796d51746a9eb270f4 Mon Sep 17 00:00:00 2001 From: q66 Date: Mon, 20 Jul 2015 18:51:16 +0100 Subject: [PATCH] hash chunk cache line boundary alignment optimization --- ostd/internal/hashtable.hh | 72 ++++++++++++++++++++++++++++++++------ 1 file changed, 62 insertions(+), 10 deletions(-) diff --git a/ostd/internal/hashtable.hh b/ostd/internal/hashtable.hh index c2de3d0..abad3c4 100644 --- a/ostd/internal/hashtable.hh +++ b/ostd/internal/hashtable.hh @@ -7,6 +7,7 @@ #define OSTD_INTERNAL_HASHTABLE_HH #include +#include #include "ostd/types.hh" #include "ostd/utility.hh" @@ -120,6 +121,63 @@ public: }; 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 + struct HashChainAlign { + static constexpr Size csize = sizeof(HashChain[N]) + sizeof(void *); + static constexpr Size value = ((csize % CACHE_LINE_SIZE) == 0) + ? N : HashChainAlign::value; + }; + + template + struct HashChainAlign { + static constexpr Size value = CHUNK_UPPER_BOUND; + }; + + template + struct HashChainPad; + + template + struct HashChainPad {}; + + template + struct HashChainPad { + byte pad[CACHE_LINE_SIZE - (N % CACHE_LINE_SIZE)]; + }; + + template + struct HashPad: HashChainPad {}; + + template::value, + bool P = (V == CHUNK_UPPER_BOUND) + > struct HashChunk; + + template + struct HashChunk { + static constexpr Size num = V; + HashChain chains[num]; + HashChunk *next; + }; + + template + struct HashChunk: HashPad< + sizeof(HashChain[V]) + sizeof(void *) + > { + static constexpr Size num = V; + HashChain chains[num]; + HashChunk *next; + }; + template< typename B, /* contains methods specific to each ht type */ typename E, /* element type */ @@ -131,14 +189,8 @@ namespace detail { bool Multihash > struct Hashtable { private: - static constexpr Size CHUNKSIZE = 64; - - using Chain = detail::HashChain; - - struct Chunk { - Chain chains[CHUNKSIZE]; - Chunk *next; - }; + using Chain = HashChain; + using Chunk = HashChunk; Size p_size; Size p_len; @@ -203,9 +255,9 @@ private: allocator_construct(get_challoc(), chunk); chunk->next = p_chunks; 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[CHUNKSIZE - 1].next = p_unused; + chunk->chains[Chunk::num - 1].next = p_unused; p_unused = chunk->chains; } ++p_len;