Replace khash with custom hash set

This commit is contained in:
Antonio S. Musumeci 2026-04-10 22:04:50 -04:00 • committed by trapexit
parent 4c9a9d7e15
commit cdadda5eb9

View file

@ -19,42 +19,49 @@
#pragma once
#include "base_types.h"
#include "khash/khash.h"
#include "rapidhash/rapidhash.h"
KHASH_SET_INIT_INT64(hashset);
#include <cstring>
// Stores 64-bit hashes only, not keys. Relies on collision
// probability being extremely low at 64-bit width.
class HashSet
{
private:
static constexpr size_t INLINE_CAPACITY = 8;
static constexpr size_t INITIAL_CAPACITY = 128;
private:
u64 _inline[INLINE_CAPACITY] = {};
u64 *_table = nullptr;
size_t _size = 0;
size_t _capacity = 0;
size_t _mask = 0;
public:
HashSet()
{
_set = kh_init(hashset);
}
HashSet() = default;
~HashSet()
{
kh_destroy(hashset,_set);
delete[] _table;
}
HashSet(const HashSet&) = delete;
HashSet& operator=(const HashSet&) = delete;
inline
int
put(const char *str_,
cu64 len_)
{
int rv;
u64 h;
khint_t key;
h = rapidhash(str_,len_);
if(h == 0)
h = 1;
key = kh_put(hashset,_set,h,&rv);
if(rv == 0)
return 0;
kh_key(_set,key) = h;
return rv;
return _put_hash(h);
}
inline
@ -66,11 +73,110 @@ public:
inline
int
size(void)
size(void) const
{
return kh_size(_set);
return _size;
}
private:
khash_t(hashset) *_set;
inline
int
_put_hash(const u64 h_)
{
if(_table == nullptr)
{
for(size_t i = 0; i < _size; ++i)
{
if(_inline[i] == h_)
return 0;
}
if(_size < INLINE_CAPACITY)
{
_inline[_size++] = h_;
return 1;
}
_grow(INITIAL_CAPACITY);
}
// 75% was benchmarked to be best generally
if(((_size + 1) * 4) >= (_capacity * 3))
_grow(_capacity * 2);
size_t idx = h_ & _mask;
while(true)
{
const u64 cur = _table[idx];
if(cur == 0)
{
_table[idx] = h_;
++_size;
return 1;
}
if(cur == h_)
return 0;
idx = ((idx + 1) & _mask);
}
}
inline
void
_grow(size_t min_capacity_)
{
size_t cap = 1;
u64 *table;
size_t mask;
while(cap < min_capacity_)
cap <<= 1;
table = new u64[cap]();
mask = cap - 1;
if(_table == nullptr)
{
for(size_t i = 0; i < _size; ++i)
_insert_existing(table,
mask,
_inline[i]);
}
else
{
for(size_t i = 0; i < _capacity; ++i)
{
const u64 h = _table[i];
if(h == 0)
continue;
_insert_existing(table,
mask,
h);
}
delete[] _table;
}
_table = table;
_capacity = cap;
_mask = mask;
}
static
inline
void
_insert_existing(u64 *table_,
size_t mask_,
u64 h_)
{
size_t idx = h_ & mask_;
while(table_[idx] != 0)
idx = ((idx + 1) & mask_);
table_[idx] = h_;
}
};