diff --git a/benchmarks/fib.py b/benchmarks/fib.py index 377a1a87..1bb89670 100644 --- a/benchmarks/fib.py +++ b/benchmarks/fib.py @@ -3,4 +3,6 @@ def fib(n): return n return fib(n-1) + fib(n-2) -assert fib(32) == 2178309 \ No newline at end of file +assert fib(32) == 2178309 + +# 7049155 calls \ No newline at end of file diff --git a/run_profile.sh b/run_profile.sh new file mode 100644 index 00000000..d345e39c --- /dev/null +++ b/run_profile.sh @@ -0,0 +1,5 @@ +# THIS SCRIPT IS NOT WORKING +clang++ -pg -O2 -std=c++17 -fno-rtti -stdlib=libc++ -Wall -o pocketpy src/main.cpp +time ./pocketpy benchmarks/fib.py +gprof pocketpy gmon.out > gprof.txt +rm gmon.out \ No newline at end of file diff --git a/src/common.h b/src/common.h index 8717cba5..5a41d237 100644 --- a/src/common.h +++ b/src/common.h @@ -41,8 +41,6 @@ #define DEBUG_NO_AUTO_GC 0 #define DEBUG_GC_STATS 0 -#define DEBUG_FRAME_USE_POOL 0 - #if (defined(__ANDROID__) && __ANDROID_API__ <= 22) || defined(__EMSCRIPTEN__) #define PK_ENABLE_FILEIO 0 #else diff --git a/src/frame.h b/src/frame.h index 70d11921..ec253a36 100644 --- a/src/frame.h +++ b/src/frame.h @@ -163,11 +163,12 @@ struct Frame { }; -#if DEBUG_FRAME_USE_POOL -inline void frame_deleter (Frame* p) { pool256.dealloc(p); } -using Frame_ = std::unique_ptr; -#else -using Frame_ = std::unique_ptr; -#endif +struct FrameDeleter{ + void operator()(Frame* frame) const { + frame->~Frame(); + pool128.dealloc(frame); + } +}; +using Frame_ = std::unique_ptr; }; // namespace pkpy \ No newline at end of file diff --git a/src/gc.h b/src/gc.h index 4cb16eab..74739fa2 100644 --- a/src/gc.h +++ b/src/gc.h @@ -11,11 +11,9 @@ struct ManagedHeap{ std::vector _no_gc; std::vector gen; VM* vm; - MemoryPool<> pool; - ManagedHeap(VM* vm): vm(vm) {} - static const int kMinGCThreshold = 4096; + static const int kMinGCThreshold = 3072; int gc_threshold = kMinGCThreshold; int gc_counter = 0; @@ -39,7 +37,7 @@ struct ManagedHeap{ template PyObject* gcnew(Type type, T&& val){ using __T = Py_>; - PyObject* obj = new(pool.alloc<__T>()) __T(type, std::forward(val)); + PyObject* obj = new(pool128.alloc<__T>()) __T(type, std::forward(val)); gen.push_back(obj); gc_counter++; return obj; @@ -48,7 +46,7 @@ struct ManagedHeap{ template PyObject* _new(Type type, T&& val){ using __T = Py_>; - PyObject* obj = new(pool.alloc<__T>()) __T(type, std::forward(val)); + PyObject* obj = new(pool128.alloc<__T>()) __T(type, std::forward(val)); obj->gc.enabled = false; _no_gc.push_back(obj); return obj; @@ -59,7 +57,7 @@ struct ManagedHeap{ #endif ~ManagedHeap(){ - for(PyObject* obj: _no_gc) obj->~PyObject(), pool.dealloc(obj); + for(PyObject* obj: _no_gc) obj->~PyObject(), pool128.dealloc(obj); #if DEBUG_GC_STATS for(auto& [type, count]: deleted){ std::cout << "GC: " << obj_type_name(vm, type) << "=" << count << std::endl; @@ -77,7 +75,7 @@ struct ManagedHeap{ #if DEBUG_GC_STATS deleted[obj->type] += 1; #endif - obj->~PyObject(), pool.dealloc(obj); + obj->~PyObject(), pool128.dealloc(obj); } } diff --git a/src/memory.h b/src/memory.h index e5d8255f..6b1f8278 100644 --- a/src/memory.h +++ b/src/memory.h @@ -210,6 +210,13 @@ struct MemoryPool{ bool empty() const { return _free_list_size == 0; } bool full() const { return _free_list_size == __MaxBlocks; } + void tidy(){ +#if DEBUG_MEMORY_POOL + if(!full()) throw std::runtime_error("Arena::tidy() called on non-full arena"); +#endif + std::sort(_free_list, _free_list+__MaxBlocks); + } + Block* alloc(){ #if DEBUG_MEMORY_POOL if(empty()) throw std::runtime_error("Arena::alloc() called on empty arena"); @@ -244,6 +251,7 @@ struct MemoryPool{ } if(_arenas.empty()){ + // std::cout << _arenas.size() << ',' << _empty_arenas.size() << ',' << _full_arenas.size() << std::endl; if(_full_arenas.empty()){ _arenas.push_back(new Arena()); }else{ @@ -277,6 +285,7 @@ struct MemoryPool{ if(arena->full() && _arenas.size()>2){ _arenas.erase(arena); if(_full_arenas.size() < FULL_ARENA_SIZE){ + // arena->tidy(); _full_arenas.push_back(arena); }else{ delete arena; @@ -287,9 +296,6 @@ struct MemoryPool{ } ~MemoryPool(){ - // std::cout << _arenas.size() << std::endl; - // std::cout << _empty_arenas.size() << std::endl; - // std::cout << _full_arenas.size() << std::endl; _arenas.apply([](Arena* arena){ delete arena; }); _empty_arenas.apply([](Arena* arena){ delete arena; }); _full_arenas.apply([](Arena* arena){ delete arena; }); @@ -298,6 +304,6 @@ struct MemoryPool{ inline MemoryPool<64> pool64; inline MemoryPool<128> pool128; -inline MemoryPool<256> pool256; +// inline MemoryPool<256> pool256; }; // namespace pkpy diff --git a/src/vm.h b/src/vm.h index f694e3a1..da085687 100644 --- a/src/vm.h +++ b/src/vm.h @@ -189,12 +189,8 @@ public: if(callstack.size() > recursionlimit){ _error("RecursionError", "maximum recursion depth exceeded"); } -#if DEBUG_FRAME_USE_POOL - Frame* frame = new(pool256.alloc(sizeof(Frame))) Frame(std::forward(args)...); - return Frame_(frame, &frame_deleter); -#else - return std::make_unique(std::forward(args)...); -#endif + Frame* frame = new(pool128.alloc()) Frame(std::forward(args)...); + return Frame_(frame); } template