From a828551eb7145e58bdc76cb785f2527255c3e0d3 Mon Sep 17 00:00:00 2001 From: blueloveTH Date: Sun, 9 Jun 2024 18:44:43 +0800 Subject: [PATCH] add memory debug info --- include/pocketpy/common/memorypool.hpp | 2 + src/common/memorypool.cpp | 52 +++++++++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/include/pocketpy/common/memorypool.hpp b/include/pocketpy/common/memorypool.hpp index 2d5bdd54..cbe5c0ee 100644 --- a/include/pocketpy/common/memorypool.hpp +++ b/include/pocketpy/common/memorypool.hpp @@ -20,4 +20,6 @@ void* PoolObject_alloc(size_t size) noexcept; void PoolObject_dealloc(void* p) noexcept; void PoolObject_shrink_to_fit() noexcept; +void Pools_debug_info(char* buffer, int size) noexcept; + }; // namespace pkpy diff --git a/src/common/memorypool.cpp b/src/common/memorypool.cpp index 55ec1f54..2db6498e 100644 --- a/src/common/memorypool.cpp +++ b/src/common/memorypool.cpp @@ -113,7 +113,8 @@ struct MemoryPool { bool full() const { return _free_list_size == __MaxBlocks; } - size_t allocated_size() const { return __BlockSize * (__MaxBlocks - _free_list_size); } + int total_bytes() const { return __BlockSize * __MaxBlocks; } + int used_bytes() const { return __BlockSize * (__MaxBlocks - _free_list_size); } Block* alloc() { assert(!empty()); @@ -206,8 +207,14 @@ struct FixedMemoryPool { Block _blocks[BlockCount]; Block* _free_list[BlockCount]; Block** _free_list_end; + int _exceeded_bytes; + + int total_bytes() const { return BlockSize * BlockCount; } + int used_bytes() const { return (BlockCount - (_free_list_end - _free_list)) * BlockSize; } + int exceeded_bytes() const { return _exceeded_bytes; } FixedMemoryPool() { + _exceeded_bytes = 0; _free_list_end = _free_list + BlockCount; for(int i = 0; i < BlockCount; ++i) { _free_list[i] = _blocks + i; @@ -222,6 +229,7 @@ struct FixedMemoryPool { --_free_list_end; return *_free_list_end; } else { + _exceeded_bytes += BlockSize; return std::malloc(BlockSize); } } @@ -232,12 +240,13 @@ struct FixedMemoryPool { *_free_list_end = static_cast(p); ++_free_list_end; } else { + _exceeded_bytes -= BlockSize; std::free(p); } } }; -static FixedMemoryPool PoolExpr; +static FixedMemoryPool PoolExpr; static FixedMemoryPool PoolFrame; static MemoryPool<80> PoolObject; @@ -255,4 +264,43 @@ void PoolObject_dealloc(void* p) noexcept { PoolObject.dealloc(p); } void PoolObject_shrink_to_fit() noexcept { PoolObject.shrink_to_fit(); } +void Pools_debug_info(char* buffer, int size) noexcept { + double BYTES_PER_MB = 1024.0f * 1024.0f; + double BYTES_PER_KB = 1024.0f; + int n = 0; + n = snprintf( + buffer, size, "PoolExpr: %.2f KB (used) / %.2f KB (total) - %.2f KB (exceeded)\n", + PoolExpr.used_bytes() / BYTES_PER_KB, + PoolExpr.total_bytes() / BYTES_PER_KB, + PoolExpr.exceeded_bytes() / BYTES_PER_KB + ); + buffer += n; size -= n; + n = snprintf( + buffer, size, "PoolFrame: %.2f KB (used) / %.2f KB (total) - %.2f KB (exceeded)\n", + PoolFrame.used_bytes() / BYTES_PER_KB, + PoolFrame.total_bytes() / BYTES_PER_KB, + PoolFrame.exceeded_bytes() / BYTES_PER_KB + ); + buffer += n; size -= n; + // PoolObject + int empty_arenas = PoolObject._empty_arenas.size(); + int arenas = PoolObject._arenas.size(); + // print empty arenas count + n = snprintf( + buffer, size, "PoolObject: %d empty arenas, %d total arenas\n", + empty_arenas, arenas + empty_arenas + ); + buffer += n; size -= n; + // log each non-empty arena + PoolObject._arenas.apply([&](MemoryPool<80>::Arena* arena) { + n = snprintf( + buffer, size, " - %p: %.2f MB (used) / %.2f MB (total)\n", + (void*)arena, + arena->used_bytes() / BYTES_PER_MB, + arena->total_bytes() / BYTES_PER_MB + ); + buffer += n; size -= n; + }); +} + } // namespace pkpy