Configured the garbage collector for lower spikes (#88)

Did you know that the garbage collector's default settings are designed for single-threaded applications and quick start-up times? We don't care about either of these.

Configured:
- Concurrent GC (default is true) (set for clarity)
- RetainVM: segments that should be deleted are put on a standby list for future use (default is false)
- QuickJit: enabling quick JIT decreases startup time but can produce code with degraded performance characteristics; for example, the code may use more stack space, allocate more memory, and run slower. (default is true) (disabled)
- ReadyToRun: configures whether the .NET runtime uses pre-compiled code for images with available ReadyToRun data; disabling this option forces the runtime to JIT-compile framework code. (default is true) (set to false, we dont publish with this option anyway)
- TieredPGO: this setting enables dynamic (tiered) profile-guided optimization (PGO) in .NET 6 and later versions. If quick JIT is disabled but tiered compilation is enabled, only pre-compiled code participates in tiered compilation. If a method is not pre-compiled with ReadyToRun, the JIT behavior is the same as if tiered compilation were disabled.

Features:
- Set ``GCLatencyMode.Interactive`` when in-menu and emulator is paused, otherwise uses ``GCLatencyMode.LowLatency``.
- Added a new UI option in the Settings > CPU menu to toggle ``GCLatencyMode.LowLatency`` during guest runtime.

![image](/attachments/84ffc6c6-d92c-4ec5-8a95-9d72dc6f1b04)

Reviewed-on: https://git.ryujinx.app/projects/Ryubing/pulls/88
This commit is contained in:
Max
2026-05-22 23:12:19 +00:00
committed by sh0inx
parent e477ec7149
commit 4631e0a9e1
12 changed files with 127 additions and 4 deletions

View File

@@ -46,6 +46,7 @@ using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
@@ -579,6 +580,12 @@ namespace Ryujinx.Ava.Systems
{
_isActive = false;
_playTimer.Stop();
GCSettings.LatencyMode = GCLatencyMode.Interactive;
if (ConfigurationState.Instance.System.GCLowLatency)
{
Logger.Info?.Print(LogClass.Application, "Garbage collector set to interactive mode.");
}
}
private void Exit()
@@ -662,6 +669,12 @@ namespace Ryujinx.Ava.Systems
_chrono.Stop();
_playTimer.Stop();
GCSettings.LatencyMode = GCLatencyMode.Interactive;
if (ConfigurationState.Instance.System.GCLowLatency)
{
Logger.Info?.Print(LogClass.Application, "Garbage collector set to interactive mode.");
}
}
public void DisposeGpu()
@@ -915,7 +928,14 @@ namespace Ryujinx.Ava.Systems
ApplicationLibrary.LoadAndSaveMetaData(Device.Processes.ActiveApplication.ProgramIdText,
appMetadata => appMetadata.UpdatePreGame()
);
_playTimer.Start();
if (ConfigurationState.Instance.System.GCLowLatency)
{
GCSettings.LatencyMode = GCLatencyMode.LowLatency;
Logger.Info?.Print(LogClass.Application, "Garbage collector set to low latency mode.");
}
}
internal void Resume()
@@ -926,6 +946,12 @@ namespace Ryujinx.Ava.Systems
_playTimer.Start();
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI);
Logger.Info?.Print(LogClass.Emulation, "Emulation was resumed.");
if (ConfigurationState.Instance.System.GCLowLatency)
{
GCSettings.LatencyMode = GCLatencyMode.LowLatency;
Logger.Info?.Print(LogClass.Application, "Garbage collector set to low latency mode.");
}
}
internal void Pause()
@@ -936,6 +962,12 @@ namespace Ryujinx.Ava.Systems
_playTimer.Stop();
_viewModel.Title = TitleHelper.ActiveApplicationTitle(Device?.Processes.ActiveApplication, Program.Version, !ConfigurationState.Instance.ShowOldUI, LocaleManager.Instance[LocaleKeys.Paused]);
Logger.Info?.Print(LogClass.Emulation, "Emulation was paused.");
GCSettings.LatencyMode = GCLatencyMode.Interactive;
if (ConfigurationState.Instance.System.GCLowLatency)
{
Logger.Info?.Print(LogClass.Application, "Garbage collector set to interactive mode.");
}
}
private void InitEmulatedSwitch()