From 4dc14a04b3d4acc6d160ac1b317ad3835be9d73c Mon Sep 17 00:00:00 2001 From: Patedam Date: Tue, 28 Jul 2026 16:00:39 -0400 Subject: [PATCH] removing useless "realloc" feature in memory arenas --- Juliet/include/Core/Memory/MemoryArena.h | 21 +--- Juliet/src/Core/Memory/MemoryArena.cpp | 104 -------------------- Juliet/src/Core/Memory/MemoryArenaTests.cpp | 54 ---------- Juliet/src/Engine/Debug/MemoryDebugger.cpp | 18 ---- Juliet/src/Engine/Engine.cpp | 3 +- 5 files changed, 4 insertions(+), 196 deletions(-) diff --git a/Juliet/include/Core/Memory/MemoryArena.h b/Juliet/include/Core/Memory/MemoryArena.h index a907bf8..ed67307 100644 --- a/Juliet/include/Core/Memory/MemoryArena.h +++ b/Juliet/include/Core/Memory/MemoryArena.h @@ -12,14 +12,6 @@ namespace Juliet constexpr global uint64 g_Arena_Default_Commit_Size = Kilobytes(64); constexpr global uint64 k_ArenaHeaderSize = 128; - struct ArenaFreeNode - { - ArenaFreeNode* Next; - ArenaFreeNode* Previous; - index_t Position; - size_t Size; - }; - #if JULIET_DEBUG struct ArenaDebugInfo; #endif @@ -41,10 +33,6 @@ namespace Juliet Arena* FreeBlockLast; - ArenaFreeNode* FreeNodes; - - bool AllowRealloc : 1; - JULIET_DEBUG_ONLY(uint16 LostNodeCount;) JULIET_DEBUG_ONLY(bool CanReserveMore : 1;) @@ -66,9 +54,6 @@ namespace Juliet uint64 ReserveSize = g_Arena_Default_Reserve_Size; uint64 CommitSize = g_Arena_Default_Commit_Size; - // True: All push will be 32 bytes minimum - bool AllowRealloc = false; - // When false, will assert if a new block is reserved. JULIET_DEBUG_ONLY(bool CanReserveMore : 1 = true;) }; @@ -78,10 +63,8 @@ namespace Juliet JULIET_API void ArenaRelease(NonNullPtr arena); // Raw Push, can be used but templated helpers exists below - [[nodiscard]] JULIET_API void* ArenaPush(NonNullPtr arena, size_t size, size_t align, - bool shouldBeZeroed JULIET_DEBUG_ONLY(, const char* tag)); - [[nodiscard]] JULIET_API void* ArenaReallocate(NonNullPtr arena, void* oldPtr, size_t oldSize, size_t newSize, - size_t align, bool shouldBeZeroed JULIET_DEBUG_ONLY(, const char* tag)); + [[nodiscard]] JULIET_API void* ArenaPush(NonNullPtr arena, size_t size, size_t align, + bool shouldBeZeroed JULIET_DEBUG_ONLY(, const char* tag)); JULIET_API void ArenaPopTo(NonNullPtr arena, size_t position); JULIET_API void ArenaPop(NonNullPtr arena, size_t amount); JULIET_API void ArenaClear(NonNullPtr arena); diff --git a/Juliet/src/Core/Memory/MemoryArena.cpp b/Juliet/src/Core/Memory/MemoryArena.cpp index 477dca3..56ad9e4 100644 --- a/Juliet/src/Core/Memory/MemoryArena.cpp +++ b/Juliet/src/Core/Memory/MemoryArena.cpp @@ -18,12 +18,6 @@ namespace Juliet constexpr uint64 k_PageSize = Kilobytes(4); } // namespace - namespace - { - static_assert(sizeof(ArenaFreeNode) == 32, "ArenaFreeNode should be 32 bytes and not more"); - constexpr size_t k_ArenaFreeNodeSize = sizeof(ArenaFreeNode); - } // namespace - // https://github.com/EpicGamesExt/raddebugger/blob/master/src/base/base_arena.c Arena* ArenaAllocate(const ArenaParams& params JULIET_DEBUG_ONLY(, const char* name), const std::source_location& loc) @@ -51,9 +45,6 @@ namespace Juliet arena->BasePosition = 0; arena->Position = k_ArenaHeaderSize; - arena->FreeNodes = nullptr; - arena->AllowRealloc = params.AllowRealloc; - #if JULIET_DEBUG arena->CanReserveMore = params.CanReserveMore; arena->FirstDebugInfo = nullptr; @@ -86,52 +77,6 @@ namespace Juliet size_t positionPrePush = AlignPow2(current->Position, align); size_t positionPostPush = positionPrePush + size; - if (arena->AllowRealloc) - { - size = Max(size, k_ArenaFreeNodeSize); - - for (ArenaFreeNode* freeNode = current->FreeNodes; freeNode != nullptr; freeNode = freeNode->Next) - { - if (size <= freeNode->Size) - { - index_t position = freeNode->Position; - size_t remainingSize = freeNode->Size - size; - if (remainingSize < k_ArenaFreeNodeSize) - { - ArenaFreeNode* previous = freeNode->Previous; - ArenaFreeNode* next = freeNode->Next; - if (previous) - { - previous->Next = next; - } - if (next) - { - next->Previous = previous; - } - -#if JULIET_DEBUG - if (remainingSize > 0) - { - ++current->LostNodeCount; - } -#endif - } - else - { - freeNode->Position += size; - } - - auto* result = reinterpret_cast(current) + position; - if (shouldBeZeroed) - { - MemoryZero(result, size); - } - - return result; - } - } - } - // If allowed and needed, add a new block and chain it to the arena. if (current->Reserved < positionPostPush /* flags : chaining allowed */) { @@ -225,55 +170,6 @@ namespace Juliet return result; } - void* ArenaReallocate(NonNullPtr arena, void* oldPtr, size_t oldSize, size_t newSize, size_t align, - bool shouldBeZeroed JULIET_DEBUG_ONLY(, const char* tag)) - { - void* result = ArenaPush(arena, newSize, align, shouldBeZeroed JULIET_DEBUG_ONLY(, tag)); - - // Find the correct block to release - Arena* block = nullptr; - for (block = arena->Current; block != nullptr; block = block->Previous) - { - if ((reinterpret_cast(block) < static_cast(oldPtr)) && - (static_cast(oldPtr) <= (reinterpret_cast(block) + block->Reserved))) - { - break; - } - } - Assert(block != nullptr); - - // Copy old to new - MemCopy(result, oldPtr, std::min(oldSize, newSize)); - - // Zero the old memory - MemoryZero(oldPtr, oldSize); - - if (oldSize >= sizeof(ArenaFreeNode)) - { - ArenaFreeNode* freeNode = static_cast(oldPtr); - ptrdiff_t posPtr = static_cast(oldPtr) - reinterpret_cast(block); - index_t position = static_cast(posPtr); - freeNode->Position = position; - freeNode->Size = oldSize; - - // Insert at head of the free list - freeNode->Next = block->FreeNodes; - freeNode->Previous = nullptr; - if (block->FreeNodes) - { - block->FreeNodes->Previous = freeNode; - } - block->FreeNodes = freeNode; - -#if JULIET_DEBUG - // Remove the debug info for the old allocation (since it's now free) - size_t oldOffset = static_cast(static_cast(oldPtr) - reinterpret_cast(block)); - DebugArenaRemoveAllocation(block, oldOffset); -#endif - } - return result; - } - void ArenaPopTo(NonNullPtr arena, size_t position) { size_t clampedPosition = ClampBottom(k_ArenaHeaderSize, position); diff --git a/Juliet/src/Core/Memory/MemoryArenaTests.cpp b/Juliet/src/Core/Memory/MemoryArenaTests.cpp index 73811f3..c4ce89c 100644 --- a/Juliet/src/Core/Memory/MemoryArenaTests.cpp +++ b/Juliet/src/Core/Memory/MemoryArenaTests.cpp @@ -117,60 +117,6 @@ namespace Juliet::UnitTest ArenaRelease(testArena); - { - // Test reallocate - Arena* arena = ArenaAllocate({ .AllowRealloc = true } JULIET_DEBUG_ONLY(, "Test Realloc")); - char* charArray = ArenaPushArray(arena, 128); - char* secondCharArray = ArenaPushArray(arena, 128); - char* thirdCharArray = ArenaPushArray(arena, 128); - - secondCharArray = static_cast(ArenaReallocate(arena, secondCharArray, 128, 256, alignof(char), true JULIET_DEBUG_ONLY(, "ReallocChar"))); - - char* fourthCharArray = ArenaPushArray(arena, 128); - - Assert(charArray); - Assert(secondCharArray); - Assert(thirdCharArray); - Assert(fourthCharArray); - - ArenaRelease(arena); - } - - { - // Test Reallocate Shrink (Buffer Overflow Bug Check) - Arena* arena = ArenaAllocate({ .AllowRealloc = true } JULIET_DEBUG_ONLY(, "Test Shrink")); - - size_t largeSize = 100; - char* large = ArenaPushArray(arena, largeSize); - MemSet(large, 'A', largeSize); - - size_t smallSize = 50; - char* smallData = static_cast(ArenaReallocate(arena, large, largeSize, smallSize, alignof(char), true JULIET_DEBUG_ONLY(, "ResizeSmall"))); - - for (size_t i = 0; i < smallSize; ++i) - { - Assert(smallData[i] == 'A'); - } - - // Allocate next block (should be immediately after 'small') - // Don't zero it, if overflow happened it will contain 'A's - char* next = static_cast(ArenaPush(arena, 50, alignof(char), false JULIET_DEBUG_ONLY(, "OverflowCheck"))); - - bool corrupted = false; - for(size_t i = 0; i < 50; ++i) - { - if (next[i] == 'A') - { - corrupted = true; - break; - } - } - - Assert(!corrupted); - - ArenaRelease(arena); - } - printf("All Paged MemoryArena tests passed.\n"); } } // namespace Juliet::UnitTest diff --git a/Juliet/src/Engine/Debug/MemoryDebugger.cpp b/Juliet/src/Engine/Debug/MemoryDebugger.cpp index 6bb30c7..b09252b 100644 --- a/Juliet/src/Engine/Debug/MemoryDebugger.cpp +++ b/Juliet/src/Engine/Debug/MemoryDebugger.cpp @@ -450,24 +450,6 @@ namespace Juliet::Debug info = info->Next; ImGui::PopID(); } - - // Draw Free Nodes (Holes) if Realloc is enabled - if (arena->AllowRealloc && blk->FreeNodes) - { - ArenaFreeNode* freeNode = blk->FreeNodes; - while (freeNode) - { - float fxStart = pos.x + static_cast(static_cast(freeNode->Position) * scale); - float fWidth = static_cast(static_cast(freeNode->Size) * scale); - - ImVec2 fMin(fxStart, pos.y + 1); - ImVec2 fMax(fxStart + fWidth, pos.y + blockHeight - 1); - - dl->AddRectFilled(fMin, fMax, IM_COL32(50, 50, 50, 200)); - - freeNode = freeNode->Next; - } - } } pos.y += blockHeight + blockSpacing; diff --git a/Juliet/src/Engine/Engine.cpp b/Juliet/src/Engine/Engine.cpp index 6abda27..32ac523 100644 --- a/Juliet/src/Engine/Engine.cpp +++ b/Juliet/src/Engine/Engine.cpp @@ -154,7 +154,8 @@ namespace Juliet void InitializeEngine(JulietInit_Flags flags) { - EngineInstance.PlatformArena = ArenaAllocate({ .AllowRealloc = true } JULIET_DEBUG_PARAM("Platform Arena")); + EngineInstance.PlatformArena = + ArenaAllocate({ .ReserveSize = Megabytes(128) } JULIET_DEBUG_PARAM("Platform Arena")); InitializeLogManager();