Force GC to run periodically in order to reduce stuttering

This commit is contained in:
2023-05-08 21:13:55 +03:00
parent 69cdb1268a
commit da149d32cf
7 changed files with 78 additions and 3 deletions

View File

@@ -20,6 +20,7 @@
#include "Engine/Threading/MainThreadTask.h" #include "Engine/Threading/MainThreadTask.h"
#include "Engine/Threading/ThreadRegistry.h" #include "Engine/Threading/ThreadRegistry.h"
#include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUDevice.h"
#include "Engine/Scripting/ManagedCLR/MCore.h"
#include "Engine/Scripting/ScriptingType.h" #include "Engine/Scripting/ScriptingType.h"
#include "Engine/Content/Content.h" #include "Engine/Content/Content.h"
#include "Engine/Content/JsonAsset.h" #include "Engine/Content/JsonAsset.h"
@@ -309,6 +310,14 @@ void Engine::OnUpdate()
// Update services // Update services
EngineService::OnUpdate(); EngineService::OnUpdate();
#ifdef USE_NETCORE
// Force GC to run in background periodically to avoid large blocking collections causing hitches
if (Time::Update.TicksCount % 60 == 0)
{
MCore::GC::Collect(MCore::GC::MaxGeneration(), MGCCollectionMode::Forced, false, false);
}
#endif
} }
void Engine::OnLateUpdate() void Engine::OnLateUpdate()

View File

@@ -1041,6 +1041,24 @@ namespace FlaxEngine.Interop
valueHandle.Free(); valueHandle.Free();
} }
[UnmanagedCallersOnly]
internal static void GCCollect(int generation, int mode, bool blocking, bool compacting)
{
GC.Collect(generation, (GCCollectionMode)mode, blocking, compacting);
}
[UnmanagedCallersOnly]
internal static int GCMaxGeneration()
{
return GC.MaxGeneration;
}
[UnmanagedCallersOnly]
internal static void GCWaitForPendingFinalizers()
{
GC.WaitForPendingFinalizers();
}
[UnmanagedCallersOnly] [UnmanagedCallersOnly]
internal static ManagedHandle GetTypeClass(ManagedHandle typeHandle) internal static ManagedHandle GetTypeClass(ManagedHandle typeHandle)
{ {

View File

@@ -106,6 +106,8 @@ public:
{ {
static void Collect(); static void Collect();
static void Collect(int32 generation); static void Collect(int32 generation);
static void Collect(int32 generation, MGCCollectionMode collectionMode, bool blocking, bool compacting);
static int32 MaxGeneration();
static void WaitForPendingFinalizers(); static void WaitForPendingFinalizers();
static void WriteRef(void* ptr, MObject* ref); static void WriteRef(void* ptr, MObject* ref);
static void WriteValue(void* dst, void* src, int32 count, const MClass* klass); static void WriteValue(void* dst, void* src, int32 count, const MClass* klass);

View File

@@ -56,6 +56,14 @@ enum class MTypes : uint32
Enum = 0x55, Enum = 0x55,
}; };
enum class MGCCollectionMode
{
Default = 0,
Forced = 1,
Optimized = 2,
Aggressive = 3
};
#if USE_NETCORE #if USE_NETCORE
enum class MTypeAttributes : uint32; enum class MTypeAttributes : uint32;

View File

@@ -422,19 +422,36 @@ void MCore::GCHandle::Free(const MGCHandle& handle)
void MCore::GC::Collect() void MCore::GC::Collect()
{ {
PROFILE_CPU(); PROFILE_CPU();
// TODO: call System.GC.Collect() static void* GCCollectPtr = GetStaticMethodPointer(TEXT("GCCollect"));
CallStaticMethod<void, int, int, bool, bool>(GCCollectPtr, MaxGeneration(), (int)MGCCollectionMode::Default, true, false);
} }
void MCore::GC::Collect(int32 generation) void MCore::GC::Collect(int32 generation)
{ {
PROFILE_CPU(); PROFILE_CPU();
// TODO: call System.GC.Collect(int32) static void* GCCollectPtr = GetStaticMethodPointer(TEXT("GCCollect"));
CallStaticMethod<void, int, int, bool, bool>(GCCollectPtr, generation, (int)MGCCollectionMode::Default, true, false);
}
void MCore::GC::Collect(int32 generation, MGCCollectionMode collectionMode, bool blocking, bool compacting)
{
PROFILE_CPU();
static void* GCCollectPtr = GetStaticMethodPointer(TEXT("GCCollect"));
CallStaticMethod<void, int, int, bool, bool>(GCCollectPtr, generation, (int)collectionMode, blocking, compacting);
}
int32 MCore::GC::MaxGeneration()
{
static void* GCMaxGenerationPtr = GetStaticMethodPointer(TEXT("GCMaxGeneration"));
static int32 maxGeneration = CallStaticMethod<int32>(GCMaxGenerationPtr);
return maxGeneration;
} }
void MCore::GC::WaitForPendingFinalizers() void MCore::GC::WaitForPendingFinalizers()
{ {
PROFILE_CPU(); PROFILE_CPU();
// TODO: call System.GC.WaitForPendingFinalizers() static void* GCWaitForPendingFinalizersPtr = GetStaticMethodPointer(TEXT("GCWaitForPendingFinalizers"));
CallStaticMethod<void>(GCWaitForPendingFinalizersPtr);
} }
void MCore::GC::WriteRef(void* ptr, MObject* ref) void MCore::GC::WriteRef(void* ptr, MObject* ref)

View File

@@ -828,6 +828,18 @@ void MCore::GC::Collect(int32 generation)
mono_gc_collect(generation); mono_gc_collect(generation);
} }
void MCore::GC::Collect(int32 generation, MGCCollectionMode collectionMode, bool blocking, bool compacting)
{
PROFILE_CPU();
mono_gc_collect(generation);
}
int32 MCore::GC::MaxGeneration()
{
PROFILE_CPU();
return mono_gc_max_generation();
}
void MCore::GC::WaitForPendingFinalizers() void MCore::GC::WaitForPendingFinalizers()
{ {
PROFILE_CPU(); PROFILE_CPU();

View File

@@ -160,6 +160,15 @@ void MCore::GC::Collect(int32 generation)
{ {
} }
void MCore::GC::Collect(int32 generation, MGCCollectionMode collectionMode, bool blocking, bool compacting)
{
}
int32 MCore::GC::MaxGeneration()
{
return 0;
}
void MCore::GC::WaitForPendingFinalizers() void MCore::GC::WaitForPendingFinalizers()
{ {
} }