mirror of
https://github.com/pocketpy/pocketpy
synced 2025-10-20 03:20:18 +00:00
some refactor
This commit is contained in:
parent
9f3d15ca51
commit
92e4416c4e
@ -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; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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){
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
@ -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__");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user