some refactor

This commit is contained in:
blueloveTH 2023-10-13 12:46:41 +08:00
parent 9f3d15ca51
commit 92e4416c4e
6 changed files with 10 additions and 61 deletions

View File

@ -23,7 +23,6 @@ namespace pkpy {
} \
PyObject* type = vm->new_type_object(mod, #name, base); \
T::_register(vm, mod, type); \
type->attr()._try_perfect_rehash(); \
return type; \
}

View File

@ -96,14 +96,6 @@ struct SmallNameDict{
uint16_t capacity() const { return PK_SMALL_NAME_DICT_CAPACITY; }
};
inline const uint16_t kHashSeeds[] = {9629, 43049, 13267, 59509, 39251, 1249, 27689, 9719, 19913};
inline uint16_t _hash(StrName key, uint16_t mask, uint16_t hash_seed){
return ( (key).index * (hash_seed) >> 8 ) & (mask);
}
uint16_t _find_perfect_hash_seed(uint16_t capacity, const std::vector<StrName>& keys);
template<typename T>
struct LargeNameDict {
PK_ALWAYS_PASS_BY_POINTER(LargeNameDict)
@ -115,7 +107,6 @@ struct LargeNameDict {
bool _is_small;
float _load_factor;
uint16_t _size;
uint16_t _hash_seed;
uint16_t _capacity;
uint16_t _critical_size;
@ -125,7 +116,7 @@ struct LargeNameDict {
#define HASH_PROBE_1(key, ok, i) \
ok = false; \
i = _hash(key, _mask, _hash_seed); \
i = key.index & _mask; \
while(!_items[i].first.empty()) { \
if(_items[i].first == (key)) { ok = true; break; } \
i = (i + 1) & _mask; \
@ -133,9 +124,8 @@ while(!_items[i].first.empty()) { \
#define HASH_PROBE_0 HASH_PROBE_1
LargeNameDict(float load_factor=kInstAttrLoadFactor): _is_small(false), _load_factor(load_factor), _size(0), _hash_seed(kHashSeeds[0]) {
_set_capacity(kInitialCapacity);
_alloc_items();
LargeNameDict(float load_factor=kInstAttrLoadFactor): _is_small(false), _load_factor(load_factor), _size(0) {
_set_capacity_and_alloc_items(kInitialCapacity);
}
~LargeNameDict(){ free(_items); }
@ -143,13 +133,11 @@ while(!_items[i].first.empty()) { \
uint16_t size() const { return _size; }
uint16_t capacity() const { return _capacity; }
void _set_capacity(uint16_t val){
void _set_capacity_and_alloc_items(uint16_t val){
_capacity = val;
_critical_size = val * _load_factor;
_mask = val - 1;
}
void _alloc_items(){
_items = (Item*)malloc(_capacity * sizeof(Item));
memset(_items, 0, _capacity * sizeof(Item));
}
@ -160,7 +148,7 @@ while(!_items[i].first.empty()) { \
if(!ok) {
_size++;
if(_size > _critical_size){
_rehash(true);
_rehash_2x();
HASH_PROBE_1(key, ok, i);
}
_items[i].first = key;
@ -168,13 +156,10 @@ while(!_items[i].first.empty()) { \
_items[i].second = val;
}
void _rehash(bool resize){
void _rehash_2x(){
Item* old_items = _items;
uint16_t old_capacity = _capacity;
if(resize){
_set_capacity(_capacity * 2);
}
_alloc_items();
_set_capacity_and_alloc_items(_capacity * 2);
for(uint16_t i=0; i<old_capacity; i++){
if(old_items[i].first.empty()) continue;
bool ok; uint16_t j;
@ -185,11 +170,6 @@ while(!_items[i].first.empty()) { \
free(old_items);
}
void _try_perfect_rehash(){
_hash_seed = _find_perfect_hash_seed(_capacity, keys());
_rehash(false); // do not resize
}
T try_get(StrName key) const{
bool ok; uint16_t i;
HASH_PROBE_0(key, ok, i);
@ -221,7 +201,7 @@ while(!_items[i].first.empty()) { \
uint16_t pre_z = i;
uint16_t z = (i + 1) & _mask;
while(!_items[z].first.empty()){
uint16_t h = _hash(_items[z].first, _mask, _hash_seed);
uint16_t h = _items[z].first.index & _mask;
if(h != i) break;
std::swap(_items[pre_z], _items[z]);
pre_z = z;
@ -318,11 +298,6 @@ struct NameDictImpl{
else _large.apply(func);
}
void _try_perfect_rehash(){
if(is_small()) return;
_large._try_perfect_rehash();
}
std::vector<StrName> keys() const{
std::vector<StrName> v;
apply([&](StrName key, V val){

View File

@ -660,7 +660,6 @@ __NEXT_STEP:;
DISPATCH();
TARGET(END_CLASS)
_0 = POPX();
_0->attr()._try_perfect_rehash();
DISPATCH();
TARGET(STORE_CLASS_ATTR){
_name = StrName(byte.arg);

View File

@ -1,23 +1,4 @@
#include "pocketpy/namedict.h"
namespace pkpy{
uint16_t _find_perfect_hash_seed(uint16_t capacity, const std::vector<StrName>& keys){
if(keys.empty()) return kHashSeeds[0];
static std::set<uint16_t> indices;
indices.clear();
std::pair<uint16_t, float> best_score = {kHashSeeds[0], 0.0f};
const int kHashSeedsSize = sizeof(kHashSeeds) / sizeof(kHashSeeds[0]);
for(int i=0; i<kHashSeedsSize; i++){
indices.clear();
for(auto key: keys){
uint16_t index = _hash(key, capacity-1, kHashSeeds[i]);
indices.insert(index);
}
float score = indices.size() / (float)keys.size();
if(score > best_score.second) best_score = {kHashSeeds[i], score};
}
return best_score.first;
}
} // namespace pkpy

View File

@ -295,7 +295,6 @@ namespace pkpy{
path_cpnts.pop_back();
PyObject* new_mod = new_module(name_cpnt, f_join(path_cpnts));
_exec(code, new_mod);
new_mod->attr()._try_perfect_rehash();
return new_mod;
}
@ -693,10 +692,6 @@ void VM::init_builtin_types(){
builtins->attr().set("slice", _t(tp_slice));
post_init();
for(int i=0; i<_all_types.size(); i++){
_all_types[i].obj->attr()._try_perfect_rehash();
}
for(auto [k, v]: _modules.items()) v->attr()._try_perfect_rehash();
this->_main = new_module("__main__");
}

View File

@ -83,14 +83,14 @@ assert str(static_test_vec4_float) == 'vec4(3.1887, -1.0984e+06, 9, 4.5654e+12)'
assert str(static_test_vec4_int) == 'vec4(278, -1.39197e+13, 1.36422e+15, -37)'
# test __getnewargs__
element_name_list = [e for e in dir(test_vec4) if e in 'x,y,z,w']
element_name_list = ['x', 'y', 'z', 'w']
element_value_list = [getattr(test_vec4, attr) for attr in element_name_list]
_0 = tuple(element_value_list)
_1 = test_vec4.__getnewargs__()
assert (_0 == _1), (_0, _1)
# test copy
element_name_list = [e for e in dir(test_vec4) if e in 'x,y,z,w']
element_name_list = ['x', 'y', 'z', 'w']
element_value_list = [getattr(test_vec4, attr) for attr in element_name_list]
copy_element_value_list = [getattr(test_vec4.copy(), attr) for attr in element_name_list]
assert element_value_list == copy_element_value_list