From b4d03501aff8b7ff8318f562a00a6ef89adb9eb1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 3 Oct 2021 14:01:27 +0200 Subject: [PATCH] - be a bit more aggressive with the GC when not running the game loop. Since most CheckGC calls are within the main game ticker, the engine can accumulate a lot of data when creating/deleting objects in the menu or other UI parts and never manage to collect everything --- src/common/objects/dobject.cpp | 3 +++ src/common/objects/dobjgc.cpp | 1 + src/common/objects/dobjgc.h | 10 +++++++++- src/g_game.cpp | 9 +++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/common/objects/dobject.cpp b/src/common/objects/dobject.cpp index 9f4a164e4..8516229de 100644 --- a/src/common/objects/dobject.cpp +++ b/src/common/objects/dobject.cpp @@ -229,6 +229,7 @@ DObject::DObject () ObjNext = GC::Root; GCNext = nullptr; GC::Root = this; + GC::AllocCount++; } DObject::DObject (PClass *inClass) @@ -238,6 +239,7 @@ DObject::DObject (PClass *inClass) ObjNext = GC::Root; GCNext = nullptr; GC::Root = this; + GC::AllocCount++; } //========================================================================== @@ -275,6 +277,7 @@ DObject::~DObject () void DObject::Release() { + if (GC::AllocCount > 0) GC::AllocCount--; DObject **probe; // Unlink this object from the GC list. diff --git a/src/common/objects/dobjgc.cpp b/src/common/objects/dobjgc.cpp index 9afa0b0af..58b27c4b7 100644 --- a/src/common/objects/dobjgc.cpp +++ b/src/common/objects/dobjgc.cpp @@ -108,6 +108,7 @@ namespace GC size_t AllocBytes; size_t Threshold; size_t Estimate; +size_t AllocCount; DObject *Gray; DObject *Root; DObject *SoftRoots; diff --git a/src/common/objects/dobjgc.h b/src/common/objects/dobjgc.h index e3f8b85b1..d01e52cf6 100644 --- a/src/common/objects/dobjgc.h +++ b/src/common/objects/dobjgc.h @@ -43,6 +43,9 @@ namespace GC // Number of bytes currently allocated through M_Malloc/M_Realloc. extern size_t AllocBytes; + // Number of allocated objects since last CheckGC call. + extern size_t AllocCount; + // Amount of memory to allocate before triggering a collection. extern size_t Threshold; @@ -105,10 +108,15 @@ namespace GC } // Check if it's time to collect, and do a collection step if it is. - static inline void CheckGC() + static inline bool CheckGC() { + AllocCount = 0; if (AllocBytes >= Threshold) + { Step(); + return true; + } + return false; } // Forces a collection to start now. diff --git a/src/g_game.cpp b/src/g_game.cpp index fdbc18aa8..f394d1a85 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1316,6 +1316,15 @@ void G_Ticker () default: break; } + // Do some more aggressive GC maintenance when the game ticker is inactive. + if ((gamestate != GS_LEVEL && gamestate != GS_TITLELEVEL) || paused || P_CheckTickerPaused()) + { + size_t ac = std::max(10, GC::AllocCount); + for (size_t i = 0; i < ac; i++) + { + if (!GC::CheckGC()) break; + } + } // [MK] Additional ticker for UI events right after all others primaryLevel->localEventManager->PostUiTick();