Skip to content

Commit

Permalink
Unify the hash function of cache and map
Browse files Browse the repository at this point in the history
Based on the below performance analysis, the golden ratio hash is a
little bit better than map hash. Therefore, we unify the hash function
to golden ratio hash.

|Metric | map hash | golden ratio hash |
|----------+----------+-------------------|
|Dhrystone | 2.06 s| 2.07 s |
|Nqueens | 4.35 s| 4.25 s |
|Stream | 76.7 s| 75.59 s |
  • Loading branch information
qwe661234 committed Oct 16, 2023
1 parent a210f74 commit d7f591f
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 28 deletions.
39 changes: 26 additions & 13 deletions src/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@

#include "cache.h"
#include "mpool.h"

#define GOLDEN_RATIO_32 0x61C88647
#define HASH(val) \
(((val) * (GOLDEN_RATIO_32)) >> (32 - (cache_size_bits))) & (cache_size - 1)
#include "utils.h"

/* THRESHOLD is set to identify hot spots. Once the frequency of use for a block
* exceeds the THRESHOLD, the JIT compiler flow is triggered.
Expand Down Expand Up @@ -337,16 +334,23 @@ static inline void move_to_mru(cache_t *cache,

void *cache_get(cache_t *cache, uint32_t key)
{
if (!cache->capacity || hlist_empty(&cache->map->ht_list_head[HASH(key)]))
if (!cache->capacity ||
hlist_empty(
&cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)]))
return NULL;

#if RV32_HAS(ARC)
arc_entry_t *entry = NULL;
#ifdef __HAVE_TYPEOF
hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list)
hlist_for_each_entry (
entry,
&cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)],
ht_list)
#else
hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list,
arc_entry_t)
hlist_for_each_entry (
entry,
&cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)],
ht_list, arc_entry_t)
#endif
{
if (entry->key == key)
Expand Down Expand Up @@ -388,10 +392,15 @@ void *cache_get(cache_t *cache, uint32_t key)
#else /* !RV32_HAS(ARC) */
lfu_entry_t *entry = NULL;
#ifdef __HAVE_TYPEOF
hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list)
hlist_for_each_entry (
entry,
&cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)],
ht_list)
#else
hlist_for_each_entry (entry, &cache->map->ht_list_head[HASH(key)], ht_list,
lfu_entry_t)
hlist_for_each_entry (
entry,
&cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)],
ht_list, lfu_entry_t)
#endif
{
if (entry->key == key)
Expand Down Expand Up @@ -478,7 +487,9 @@ void *cache_put(cache_t *cache, uint32_t key, void *value)
list_add(&new_entry->list, cache->lists[LRU_ghost_list]);
cache->list_size[LRU_ghost_list]++;
}
hlist_add_head(&new_entry->ht_list, &cache->map->ht_list_head[HASH(key)]);
hlist_add_head(
&new_entry->ht_list,
&cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)]);

CACHE_ASSERT(cache);
#else /* !RV32_HAS(ARC) */
Expand All @@ -504,7 +515,9 @@ void *cache_put(cache_t *cache, uint32_t key, void *value)
new_entry->frequency = 0;
list_add(&new_entry->list, cache->lists[new_entry->frequency++]);
cache->list_size++;
hlist_add_head(&new_entry->ht_list, &cache->map->ht_list_head[HASH(key)]);
hlist_add_head(
&new_entry->ht_list,
&cache->map->ht_list_head[hash(key, cache_size_bits, cache_size)]);
assert(cache->list_size <= cache->capacity);
#endif
return delete_value;
Expand Down
18 changes: 4 additions & 14 deletions src/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -277,18 +277,6 @@ void rv_debug(riscv_t *rv)
}
#endif /* RV32_HAS(GDBSTUB) */

/* hash function is used when mapping address into the block map */
static inline uint32_t hash(size_t k)
{
k ^= k << 21;
k ^= k >> 17;
#if (SIZE_MAX > 0xFFFFFFFF)
k ^= k >> 35;
k ^= k >> 51;
#endif
return k;
}

/* allocate a basic block */
static block_t *block_alloc(riscv_t *rv)
{
Expand All @@ -304,7 +292,8 @@ static void block_insert(block_map_t *map, const block_t *block)
{
assert(map && block);
const uint32_t mask = map->block_capacity - 1;
uint32_t index = hash(block->pc_start);
uint32_t index = hash(block->pc_start, BLOCK_MAP_CAPACITY_BITS,
1 << BLOCK_MAP_CAPACITY_BITS);

/* insert into the block map */
for (;; index++) {
Expand All @@ -320,7 +309,8 @@ static void block_insert(block_map_t *map, const block_t *block)
static block_t *block_find(const block_map_t *map, const uint32_t addr)
{
assert(map);
uint32_t index = hash(addr);
uint32_t index =
hash(addr, BLOCK_MAP_CAPACITY_BITS, 1 << BLOCK_MAP_CAPACITY_BITS);
const uint32_t mask = map->block_capacity - 1;

/* find block in block map */
Expand Down
1 change: 0 additions & 1 deletion src/riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#include "riscv_private.h"
#include "state.h"

#define BLOCK_MAP_CAPACITY_BITS 10
#define BLOCK_IR_MAP_CAPACITY_BITS 10

/* initialize the block map */
Expand Down
2 changes: 2 additions & 0 deletions src/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ enum {
#define MSTATUS_MPIE (1 << MSTATUS_MPIE_SHIFT)
#define MSTATUS_MPP (3 << MSTATUS_MPP_SHIFT)

#define BLOCK_MAP_CAPACITY_BITS 10

/* forward declaration for internal structure */
typedef struct riscv_internal riscv_t;
typedef void *riscv_user_t;
Expand Down
7 changes: 7 additions & 0 deletions src/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,10 @@ void rv_gettimeofday(struct timeval *tv);

/* Retrieve the value used by a clock which is specified by clock_id. */
void rv_clock_gettime(struct timespec *tp);

/* Detect the instruction is RV32C or not */
FORCE_INLINE uint32_t hash(uint32_t val, uint8_t size_bits, uint32_t size)
{
/* 0x61C88647 is 32-bit golden ratio*/
return (val * 0x61C88647 >> (32 - size_bits)) & (size - 1);
}

0 comments on commit d7f591f

Please sign in to comment.