fixed missing outer loop for not finding element at first tipp + started refactor

This commit is contained in:
Richard Thier 2024-10-21 12:53:15 +02:00
parent 4ade45a655
commit cdd9c77892

81
simap.h
View File

@ -27,18 +27,22 @@
#endif
typedef uint64_t auint64 __attribute__ ((__aligned__(8)));
/** The first 8 characters are stored as uint64_t for fast checks */
union simap_c64 {
char str8[8];
auint64 u64;
};
typedef union simap_char64 simap_char64;
/** This is to ensure 8byte storage of pointers (with possible padding) */
union simap_ptr64 {
void *ptr;
auint64 u64;
};
typedef union simap_ptr64 simap_ptr64;
/**
* A "peasantly" map data structure backed by arena.h - basically a toy data structure...
*
* This is very simple, no trees, no hashes, just (hopefully) autovectorized linear lookup.
* Inserting NULLs to keys happens through tombstoning unless erase happens and we never
* shrink memory so please do not add a lot of things then remove a lot of things.
*
* We also only do heuristics against data being the key so its not "sure" and can fail...
*
* XXX: So beware that this can FAIL just "statistically most often works"!
*
* The per-elem memory layout after at *base is as follows:
* The per-element storage layout
*
* 8 byte:
* - void* value;
@ -56,13 +60,36 @@ typedef uint64_t auint64 __attribute__ ((__aligned__(8)));
* with few character names zero-padded in the search term parameter
* and if you want check extra validity by jumping back&forth in it.
*/
struct elem_prefix {
/** The value (ptr) */
simap_ptr64 value;
/** Previous element index from base (full offset) */
uint32_t previndex;
/** Next element index from base (full offset) */
uint32_t nextindex;
/** The prefix of the key */
simap_c64 key_prefix;
};
typedef struct elem_prefix elem_prefix;
/**
* A "peasantly" map data structure backed by arena.h - basically a toy data structure...
*
* This is very simple, no trees, no hashes, just (hopefully) autovectorized linear lookup.
* Inserting NULLs to keys happens through tombstoning unless erase happens and we never
* shrink memory so please do not add a lot of things then remove a lot of things.
*
* In AVX2 mode, we do heuristics against data being the key so its not "sure" and can fail...
* XXX: So beware that this CAN FAIL for AVX2 build flags just "statistically most often works"!
*/
struct simap_instance {
arena a;
uint32_t end;
uint32_t prev_usage_end; /* previous usage_end or -1 if no previous exists... in bytes!!! */
uint32_t usage_end; /* in bytes!!! */
/** see doc comment for layout and why uint64_t* is the type */
auint64 *base;
elem_prefix *base;
};
typedef struct simap_instance simap_instance;
@ -72,27 +99,13 @@ static inline simap_instance simap_create() {
ret.end = 0;
ret.prev_usage_end = (uint32_t) -1;
ret.usage_end = 0;
ret.base = ((auint64*) aralloc(&(ret.a), sizeof(auint64), sizeof(auint64), 1)) /* addr divisible by 8 */
+ 1; /* First really addressible thing */
ret.base = (elem_prefix*)(((auint64*) aralloc(&(ret.a), sizeof(auint64), sizeof(auint64), 1)) /* addr divisible by 8 */
+ 1); /* First really addressible thing */
return ret;
}
static inline void* simap(void *amap_instance, AMAP_OP op, const char *key, void *ptr);
/** The first 8 characters are stored as uint64_t for fast checks */
union simap_c64 {
char str8[8];
auint64 u64;
};
typedef union simap_char64 simap_char64;
/** This is to ensure 8byte storage of pointers (with possible padding) */
union simap_ptr64 {
void *ptr;
auint64 u64;
};
typedef union simap_ptr64 simap_ptr64;
// TODO: We can possibly hand-optimise this with intrinsics maybe - but I hope autovectorization (does not seem to happen???)
static inline SM_ALWAYS_INLINE auint64 *make_tipp(auint64 *tip, auint64 prefix, auint64 *end) {
#pragma GCC unroll 4
@ -113,9 +126,12 @@ static inline simap_ptr64 *simap_search_internal(simap_instance *map, const char
const char *keyremains = key + prefixlen;
/* Lookup prefix (fast-key) - hopefully this gets vectorized (should be)!!! */
auint64 *base = map->base;
auint64 *base = (auint64 *) (map->base);
auint64 *end = (auint64 *)((uint8_t *)base + (map->usage_end));
auint64 *tipp = make_tipp(map->base, prefix.u64, end);
auint64 *tipp = NULL;
auint64 *nutipp = make_tipp(base, prefix.u64, end);
while(tipp != nutipp) {
tipp = nutipp;
while(tipp < end) {
/* Fast lookup, because found prefix */
assert((*tipp == prefix.u64));
@ -151,7 +167,8 @@ static inline simap_ptr64 *simap_search_internal(simap_instance *map, const char
/* Can have the (statistically checked) pointer */
return ptr;
}
tipp = make_tipp(map->base, prefix.u64, end);
nutipp = make_tipp((auint64 *) base, prefix.u64, end);
}
/* Haven't found anything */
return NULL;