Skip to content

Commit

Permalink
Using bytes for flags, simplifying flag logic and imrpoving performance.
Browse files Browse the repository at this point in the history
Increases flag memory usage by 300%, while significantly streamlining
logic and improving performance
  • Loading branch information
dwforbes committed Jun 6, 2017
1 parent 9b12aa4 commit 348601f
Showing 1 changed file with 16 additions and 13 deletions.
29 changes: 16 additions & 13 deletions khash.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ int main() {
#include <limits.h>

/* compiler specific configuration */
typedef unsigned char khint8_t;

#if UINT_MAX == 0xffffffffu
typedef unsigned int khint32_t;
Expand Down Expand Up @@ -162,15 +163,17 @@ typedef unsigned long long khint64_t;
typedef khint32_t khint_t;
typedef khint_t khiter_t;

#define __ac_isempty(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&2)
#define __ac_isdel(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&1)
#define __ac_iseither(flag, i) ((flag[i>>4]>>((i&0xfU)<<1))&3)
#define __ac_set_isdel_false(flag, i) (flag[i>>4]&=~(1ul<<((i&0xfU)<<1)))
#define __ac_set_isempty_false(flag, i) (flag[i>>4]&=~(2ul<<((i&0xfU)<<1)))
#define __ac_set_isboth_false(flag, i) (flag[i>>4]&=~(3ul<<((i&0xfU)<<1)))
#define __ac_set_isdel_true(flag, i) (flag[i>>4]|=1ul<<((i&0xfU)<<1))
#define __ac_bit_empty 0b00000010
#define __ac_bit_deleted 0b00000001
#define __ac_bit_any 0b11111111

#define __ac_fsize(m) ((m) < 16? 1 : (m)>>4)
#define __ac_isempty(flag, i) (flag[i]&__ac_bit_empty)
#define __ac_isdel(flag, i) (flag[i]&__ac_bit_deleted)
#define __ac_iseither(flag, i) (flag[i]&__ac_bit_any)
#define __ac_set_isdel_false(flag, i) (flag[i]&=~__ac_bit_deleted)
#define __ac_set_isempty_false(flag, i) (flag[i]&=~__ac_bit_empty)
#define __ac_set_isboth_false(flag, i) (flag[i]=0)
#define __ac_set_isdel_true(flag, i) (flag[i]|=__ac_bit_deleted)

#ifndef kroundup32
#define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x))
Expand All @@ -194,7 +197,7 @@ static const double __ac_HASH_UPPER = 0.77;
#define __KHASH_TYPE(name, khkey_t, khval_t) \
typedef struct kh_##name##_s { \
khint_t n_buckets, size, n_occupied, upper_bound; \
khint32_t *flags; \
khint8_t *flags; \
khkey_t *keys; \
khval_t *vals; \
} kh_##name##_t;
Expand Down Expand Up @@ -223,7 +226,7 @@ static const double __ac_HASH_UPPER = 0.77;
SCOPE void kh_clear_##name(kh_##name##_t *h) \
{ \
if (h && h->flags) { \
memset(h->flags, 0xaa, __ac_fsize(h->n_buckets) * sizeof(khint32_t)); \
memset(h->flags, __ac_bit_empty, h->n_buckets); \
h->size = h->n_occupied = 0; \
} \
} \
Expand All @@ -243,16 +246,16 @@ static const double __ac_HASH_UPPER = 0.77;
} \
SCOPE int kh_resize_##name(kh_##name##_t *h, khint_t new_n_buckets) \
{ /* This function uses 0.25*n_buckets bytes of working space instead of [sizeof(key_t+val_t)+.25]*n_buckets. */ \
khint32_t *new_flags = 0; \
khint8_t *new_flags = 0; \
khint_t j = 1; \
{ \
kroundup32(new_n_buckets); \
if (new_n_buckets < 4) new_n_buckets = 4; \
if (h->size >= (khint_t)(new_n_buckets * __ac_HASH_UPPER + 0.5)) j = 0; /* requested size is too small */ \
else { /* hash table size to be changed (shrink or expand); rehash */ \
new_flags = (khint32_t*)kmalloc(__ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
new_flags = (khint8_t*)kmalloc(new_n_buckets); \
if (!new_flags) return -1; \
memset(new_flags, 0xaa, __ac_fsize(new_n_buckets) * sizeof(khint32_t)); \
memset(new_flags, __ac_bit_empty, new_n_buckets); \
if (h->n_buckets < new_n_buckets) { /* expand */ \
khkey_t *new_keys = (khkey_t*)krealloc((void *)h->keys, new_n_buckets * sizeof(khkey_t)); \
if (!new_keys) { kfree(new_flags); return -1; } \
Expand Down

0 comments on commit 348601f

Please sign in to comment.