This commit is contained in:
blueloveTH 2024-06-09 21:26:54 +08:00
parent 0946c67fe0
commit 4b687d36ff
6 changed files with 36 additions and 29 deletions

View File

@ -10,13 +10,14 @@ namespace pkpy {
const inline int kPoolExprBlockSize = 128; const inline int kPoolExprBlockSize = 128;
const inline int kPoolFrameBlockSize = 80; const inline int kPoolFrameBlockSize = 80;
const inline int kPoolObjectBlockSize = 80;
void* PoolExpr_alloc() noexcept; void* PoolExpr_alloc() noexcept;
void PoolExpr_dealloc(void*) noexcept; void PoolExpr_dealloc(void*) noexcept;
void* PoolFrame_alloc() noexcept; void* PoolFrame_alloc() noexcept;
void PoolFrame_dealloc(void*) noexcept; void PoolFrame_dealloc(void*) noexcept;
void* PoolObject_alloc(size_t size) noexcept; void* PoolObject_alloc() noexcept;
void PoolObject_dealloc(void* p) noexcept; void PoolObject_dealloc(void* p) noexcept;
void PoolObject_shrink_to_fit() noexcept; void PoolObject_shrink_to_fit() noexcept;

View File

@ -40,7 +40,12 @@ struct ManagedHeap {
using __T = std::decay_t<T>; using __T = std::decay_t<T>;
static_assert(!is_sso_v<__T>, "gcnew cannot be used with SSO types"); static_assert(!is_sso_v<__T>, "gcnew cannot be used with SSO types");
// https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476 // https://github.com/pocketpy/pocketpy/issues/94#issuecomment-1594784476
PyObject* p = new (PoolObject_alloc(py_sizeof<__T>)) PyObject(type); PyObject* p;
if constexpr(py_sizeof<__T> <= kPoolObjectBlockSize){
p = new (PoolObject_alloc()) PyObject(type, false);
}else{
p = new (std::malloc(py_sizeof<__T>)) PyObject(type, true);
}
p->placement_new<__T>(std::forward<Args>(args)...); p->placement_new<__T>(std::forward<Args>(args)...);
gen.push_back(p); gen.push_back(p);
gc_counter++; gc_counter++;
@ -51,7 +56,12 @@ struct ManagedHeap {
PyObject* _new(Type type, Args&&... args) { PyObject* _new(Type type, Args&&... args) {
using __T = std::decay_t<T>; using __T = std::decay_t<T>;
static_assert(!is_sso_v<__T>); static_assert(!is_sso_v<__T>);
PyObject* p = new (PoolObject_alloc(py_sizeof<__T>)) PyObject(type); PyObject* p;
if constexpr(py_sizeof<__T> <= kPoolObjectBlockSize){
p = new (PoolObject_alloc()) PyObject(type, false);
}else{
p = new (std::malloc(py_sizeof<__T>)) PyObject(type, true);
}
p->placement_new<__T>(std::forward<Args>(args)...); p->placement_new<__T>(std::forward<Args>(args)...);
_no_gc.push_back(p); _no_gc.push_back(p);
return p; return p;

View File

@ -9,8 +9,9 @@ namespace pkpy {
struct NameDict; struct NameDict;
struct PyObject final { struct PyObject final {
bool gc_marked; // whether this object is marked
Type type; // we have a duplicated type here for convenience Type type; // we have a duplicated type here for convenience
bool gc_is_large;
bool gc_marked;
NameDict* _attr; // gc will delete this on destruction NameDict* _attr; // gc will delete this on destruction
bool is_attr_valid() const noexcept { return _attr != nullptr; } bool is_attr_valid() const noexcept { return _attr != nullptr; }
@ -28,7 +29,7 @@ struct PyObject final {
return *_attr; return *_attr;
} }
PyObject(Type type) : gc_marked(false), type(type), _attr(nullptr) {} PyObject(Type type, bool gc_is_large) : type(type), gc_is_large(gc_is_large), gc_marked(false), _attr(nullptr) {}
PyVar attr(StrName name) const; PyVar attr(StrName name) const;
static NameDict* __init_namedict(float lf); static NameDict* __init_namedict(float lf);

View File

@ -87,8 +87,8 @@ struct DoubleLinkedList {
} }
}; };
template <int __BlockSize>
struct MemoryPool { struct MemoryPool {
const static int __BlockSize = kPoolObjectBlockSize;
const static int __MaxBlocks = 256 * 1024 / __BlockSize; const static int __MaxBlocks = 256 * 1024 / __BlockSize;
const static int __MinArenaCount = PK_GC_MIN_THRESHOLD * 100 / (256 * 1024); const static int __MinArenaCount = PK_GC_MIN_THRESHOLD * 100 / (256 * 1024);
@ -138,14 +138,8 @@ struct MemoryPool {
DoubleLinkedList<Arena> _arenas; DoubleLinkedList<Arena> _arenas;
DoubleLinkedList<Arena> _empty_arenas; DoubleLinkedList<Arena> _empty_arenas;
void* alloc(size_t size) { void* alloc() {
PK_GLOBAL_SCOPE_LOCK(); PK_GLOBAL_SCOPE_LOCK();
if(size > __BlockSize) {
void* p = std::malloc(sizeof(void*) + size);
std::memset(p, 0, sizeof(void*));
return (char*)p + sizeof(void*);
}
if(_arenas.empty()) { _arenas.push_back(new Arena()); } if(_arenas.empty()) { _arenas.push_back(new Arena()); }
Arena* arena = _arenas.back(); Arena* arena = _arenas.back();
void* p = arena->alloc()->data; void* p = arena->alloc()->data;
@ -160,17 +154,14 @@ struct MemoryPool {
PK_GLOBAL_SCOPE_LOCK(); PK_GLOBAL_SCOPE_LOCK();
assert(p != nullptr); assert(p != nullptr);
Block* block = (Block*)((char*)p - sizeof(void*)); Block* block = (Block*)((char*)p - sizeof(void*));
if(block->arena == nullptr) { assert(block->arena != nullptr);
std::free(block); Arena* arena = (Arena*)block->arena;
if(arena->empty()) {
_empty_arenas.erase(arena);
_arenas.push_front(arena);
arena->dealloc(block);
} else { } else {
Arena* arena = (Arena*)block->arena; arena->dealloc(block);
if(arena->empty()) {
_empty_arenas.erase(arena);
_arenas.push_front(arena);
arena->dealloc(block);
} else {
arena->dealloc(block);
}
} }
} }
@ -248,7 +239,7 @@ struct FixedMemoryPool {
static FixedMemoryPool<kPoolExprBlockSize, 64> PoolExpr; static FixedMemoryPool<kPoolExprBlockSize, 64> PoolExpr;
static FixedMemoryPool<kPoolFrameBlockSize, 128> PoolFrame; static FixedMemoryPool<kPoolFrameBlockSize, 128> PoolFrame;
static MemoryPool<80> PoolObject; static MemoryPool PoolObject;
void* PoolExpr_alloc() noexcept { return PoolExpr.alloc(); } void* PoolExpr_alloc() noexcept { return PoolExpr.alloc(); }
@ -258,7 +249,7 @@ void* PoolFrame_alloc() noexcept { return PoolFrame.alloc(); }
void PoolFrame_dealloc(void* p) noexcept { PoolFrame.dealloc(p); } void PoolFrame_dealloc(void* p) noexcept { PoolFrame.dealloc(p); }
void* PoolObject_alloc(size_t size) noexcept { return PoolObject.alloc(size); } void* PoolObject_alloc() noexcept { return PoolObject.alloc(); }
void PoolObject_dealloc(void* p) noexcept { PoolObject.dealloc(p); } void PoolObject_dealloc(void* p) noexcept { PoolObject.dealloc(p); }
@ -292,7 +283,7 @@ void Pools_debug_info(char* buffer, int size) noexcept {
); );
buffer += n; size -= n; buffer += n; size -= n;
// log each non-empty arena // log each non-empty arena
PoolObject._arenas.apply([&](MemoryPool<80>::Arena* arena) { PoolObject._arenas.apply([&](MemoryPool::Arena* arena) {
n = snprintf( n = snprintf(
buffer, size, " - %p: %.2f MB (used) / %.2f MB (total)\n", buffer, size, " - %p: %.2f MB (used) / %.2f MB (total)\n",
(void*)arena, (void*)arena,

View File

@ -1902,7 +1902,11 @@ void ManagedHeap::_delete(PyObject* obj) {
const PyTypeInfo* ti = vm->_tp_info(obj->type); const PyTypeInfo* ti = vm->_tp_info(obj->type);
if(ti->vt._dtor) ti->vt._dtor(obj->_value_ptr()); if(ti->vt._dtor) ti->vt._dtor(obj->_value_ptr());
delete obj->_attr; // delete __dict__ if exists delete obj->_attr; // delete __dict__ if exists
PoolObject_dealloc(obj); if(obj->gc_is_large){
std::free(obj);
}else{
PoolObject_dealloc(obj);
}
} }
void Dict::_gc_mark(VM* vm) const { void Dict::_gc_mark(VM* vm) const {

View File

@ -1,6 +1,6 @@
#include "pocketpy/objects/builtins.hpp" #include "pocketpy/objects/builtins.hpp"
namespace pkpy { namespace pkpy {
const PyVar PY_OP_CALL(Type(), new PyObject(Type())); const PyVar PY_OP_CALL(Type(), new PyObject(Type(), true));
const PyVar PY_OP_YIELD(Type(), new PyObject(Type())); const PyVar PY_OP_YIELD(Type(), new PyObject(Type(), true));
} // namespace pkpy } // namespace pkpy