Skip to content

Commit

Permalink
Merge pull request #27891 from peppy/stop-background-process-high-per…
Browse files Browse the repository at this point in the history
…formance

Fix high memory usage during spectator modes when background processing is running
  • Loading branch information
bdach authored Apr 16, 2024
2 parents 0e218ee + 926424d commit 2c90ba9
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 5 deletions.
25 changes: 21 additions & 4 deletions osu.Desktop/Performance/HighPerformanceSessionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System;
using System.Runtime;
using System.Threading;
using osu.Framework.Allocation;
using osu.Framework.Logging;
using osu.Game.Performance;
Expand All @@ -11,16 +12,26 @@ namespace osu.Desktop.Performance
{
public class HighPerformanceSessionManager : IHighPerformanceSessionManager
{
public bool IsSessionActive => activeSessions > 0;

private int activeSessions;

private GCLatencyMode originalGCMode;

public IDisposable BeginSession()
{
enableHighPerformanceSession();
return new InvokeOnDisposal<HighPerformanceSessionManager>(this, static m => m.disableHighPerformanceSession());
enterSession();
return new InvokeOnDisposal<HighPerformanceSessionManager>(this, static m => m.exitSession());
}

private void enableHighPerformanceSession()
private void enterSession()
{
if (Interlocked.Increment(ref activeSessions) > 1)
{
Logger.Log($"High performance session requested ({activeSessions} running in total)");
return;
}

Logger.Log("Starting high performance session");

originalGCMode = GCSettings.LatencyMode;
Expand All @@ -30,8 +41,14 @@ private void enableHighPerformanceSession()
GC.Collect(0);
}

private void disableHighPerformanceSession()
private void exitSession()
{
if (Interlocked.Decrement(ref activeSessions) > 0)
{
Logger.Log($"High performance session finished ({activeSessions} others remain)");
return;
}

Logger.Log("Ending high performance session");

if (GCSettings.LatencyMode == GCLatencyMode.LowLatency)
Expand Down
8 changes: 7 additions & 1 deletion osu.Game/Database/BackgroundDataStoreProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using osu.Game.Online.API;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using osu.Game.Performance;
using osu.Game.Rulesets;
using osu.Game.Scoring;
using osu.Game.Scoring.Legacy;
Expand Down Expand Up @@ -51,6 +52,9 @@ public partial class BackgroundDataStoreProcessor : Component
[Resolved]
private ILocalUserPlayInfo? localUserPlayInfo { get; set; }

[Resolved]
private IHighPerformanceSessionManager? highPerformanceSessionManager { get; set; }

[Resolved]
private INotificationOverlay? notificationOverlay { get; set; }

Expand Down Expand Up @@ -493,7 +497,9 @@ private void completeNotification(ProgressNotification? notification, int proces

private void sleepIfRequired()
{
while (localUserPlayInfo?.IsPlaying.Value == true)
// Importantly, also sleep if high performance session is active.
// If we don't do this, memory usage can become runaway due to GC running in a more lenient mode.
while (localUserPlayInfo?.IsPlaying.Value == true || highPerformanceSessionManager?.IsSessionActive == true)
{
Logger.Log("Background processing sleeping due to active gameplay...");
Thread.Sleep(TimeToSleepDuringGameplay);
Expand Down
5 changes: 5 additions & 0 deletions osu.Game/Performance/IHighPerformanceSessionManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ namespace osu.Game.Performance
/// </summary>
public interface IHighPerformanceSessionManager
{
/// <summary>
/// Whether a high performance session is currently active.
/// </summary>
bool IsSessionActive { get; }

/// <summary>
/// Start a new high performance session.
/// </summary>
Expand Down

0 comments on commit 2c90ba9

Please sign in to comment.