1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-27 13:23:05 +08:00

Merge pull request #27891 from peppy/stop-background-process-high-performance

Fix high memory usage during spectator modes when background processing is running
This commit is contained in:
Bartłomiej Dach 2024-04-16 10:57:33 +02:00 committed by GitHub
commit 2c90ba9614
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 33 additions and 5 deletions

View File

@ -3,6 +3,7 @@
using System; using System;
using System.Runtime; using System.Runtime;
using System.Threading;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Game.Performance; using osu.Game.Performance;
@ -11,16 +12,26 @@ namespace osu.Desktop.Performance
{ {
public class HighPerformanceSessionManager : IHighPerformanceSessionManager public class HighPerformanceSessionManager : IHighPerformanceSessionManager
{ {
public bool IsSessionActive => activeSessions > 0;
private int activeSessions;
private GCLatencyMode originalGCMode; private GCLatencyMode originalGCMode;
public IDisposable BeginSession() public IDisposable BeginSession()
{ {
enableHighPerformanceSession(); enterSession();
return new InvokeOnDisposal<HighPerformanceSessionManager>(this, static m => m.disableHighPerformanceSession()); 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"); Logger.Log("Starting high performance session");
originalGCMode = GCSettings.LatencyMode; originalGCMode = GCSettings.LatencyMode;
@ -30,8 +41,14 @@ namespace osu.Desktop.Performance
GC.Collect(0); 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"); Logger.Log("Ending high performance session");
if (GCSettings.LatencyMode == GCLatencyMode.LowLatency) if (GCSettings.LatencyMode == GCLatencyMode.LowLatency)

View File

@ -16,6 +16,7 @@ using osu.Game.Extensions;
using osu.Game.Online.API; using osu.Game.Online.API;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Notifications;
using osu.Game.Performance;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Scoring; using osu.Game.Scoring;
using osu.Game.Scoring.Legacy; using osu.Game.Scoring.Legacy;
@ -51,6 +52,9 @@ namespace osu.Game.Database
[Resolved] [Resolved]
private ILocalUserPlayInfo? localUserPlayInfo { get; set; } private ILocalUserPlayInfo? localUserPlayInfo { get; set; }
[Resolved]
private IHighPerformanceSessionManager? highPerformanceSessionManager { get; set; }
[Resolved] [Resolved]
private INotificationOverlay? notificationOverlay { get; set; } private INotificationOverlay? notificationOverlay { get; set; }
@ -493,7 +497,9 @@ namespace osu.Game.Database
private void sleepIfRequired() 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..."); Logger.Log("Background processing sleeping due to active gameplay...");
Thread.Sleep(TimeToSleepDuringGameplay); Thread.Sleep(TimeToSleepDuringGameplay);

View File

@ -14,6 +14,11 @@ namespace osu.Game.Performance
/// </summary> /// </summary>
public interface IHighPerformanceSessionManager public interface IHighPerformanceSessionManager
{ {
/// <summary>
/// Whether a high performance session is currently active.
/// </summary>
bool IsSessionActive { get; }
/// <summary> /// <summary>
/// Start a new high performance session. /// Start a new high performance session.
/// </summary> /// </summary>