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); \ PyObject* type = vm->new_type_object(mod, #name, base); \
T::_register(vm, mod, type); \ T::_register(vm, mod, type); \
type->attr()._try_perfect_rehash(); \
return type; \ return type; \
} }

View File

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

View File

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

View File

@ -1,23 +1,4 @@
#include "pocketpy/namedict.h" #include "pocketpy/namedict.h"
namespace pkpy{ 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 } // namespace pkpy

View File

@ -295,7 +295,6 @@ namespace pkpy{
path_cpnts.pop_back(); path_cpnts.pop_back();
PyObject* new_mod = new_module(name_cpnt, f_join(path_cpnts)); PyObject* new_mod = new_module(name_cpnt, f_join(path_cpnts));
_exec(code, new_mod); _exec(code, new_mod);
new_mod->attr()._try_perfect_rehash();
return new_mod; return new_mod;
} }
@ -693,10 +692,6 @@ void VM::init_builtin_types(){
builtins->attr().set("slice", _t(tp_slice)); builtins->attr().set("slice", _t(tp_slice));
post_init(); 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__"); 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)' assert str(static_test_vec4_int) == 'vec4(278, -1.39197e+13, 1.36422e+15, -37)'
# test __getnewargs__ # 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] element_value_list = [getattr(test_vec4, attr) for attr in element_name_list]
_0 = tuple(element_value_list) _0 = tuple(element_value_list)
_1 = test_vec4.__getnewargs__() _1 = test_vec4.__getnewargs__()
assert (_0 == _1), (_0, _1) assert (_0 == _1), (_0, _1)
# test copy # 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] 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] copy_element_value_list = [getattr(test_vec4.copy(), attr) for attr in element_name_list]
assert element_value_list == copy_element_value_list assert element_value_list == copy_element_value_list