1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 04:13:00 +08:00

Merge pull request #2791 from peppy/fix-memory-leak

Fix gameplay memory leak due to incorrect binding
This commit is contained in:
Dan Balasescu 2018-06-14 02:47:08 +09:00 committed by GitHub
commit af4d4b529f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 40 additions and 5 deletions

View File

@ -161,7 +161,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
}; };
this.beatmap.BindTo(beatmap); this.beatmap.BindTo(beatmap);
beatmap.ValueChanged += v => calculateScale(); this.beatmap.ValueChanged += v => calculateScale();
cursorScale = config.GetBindable<double>(OsuSetting.GameplayCursorSize); cursorScale = config.GetBindable<double>(OsuSetting.GameplayCursorSize);
cursorScale.ValueChanged += v => calculateScale(); cursorScale.ValueChanged += v => calculateScale();

View File

@ -1,9 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Linq; using System.Linq;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Framework.Lists;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
@ -51,6 +53,28 @@ namespace osu.Game.Tests.Visual
Player p = null; Player p = null;
AddStep(r.Name, () => p = loadPlayerFor(r)); AddStep(r.Name, () => p = loadPlayerFor(r));
AddUntilStep(() => ContinueCondition(p)); AddUntilStep(() => ContinueCondition(p));
AddAssert("no leaked beatmaps", () =>
{
p = null;
GC.Collect();
GC.WaitForPendingFinalizers();
int count = 0;
workingWeakReferences.ForEachAlive(_ => count++);
return count == 1;
});
AddAssert("no leaked players", () =>
{
GC.Collect();
GC.WaitForPendingFinalizers();
int count = 0;
playerWeakReferences.ForEachAlive(_ => count++);
return count == 1;
});
} }
} }
} }
@ -59,21 +83,32 @@ namespace osu.Game.Tests.Visual
protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo); protected virtual IBeatmap CreateBeatmap(Ruleset ruleset) => new TestBeatmap(ruleset.RulesetInfo);
private readonly WeakList<WorkingBeatmap> workingWeakReferences = new WeakList<WorkingBeatmap>();
private readonly WeakList<Player> playerWeakReferences = new WeakList<Player>();
private Player loadPlayerFor(RulesetInfo ri) => loadPlayerFor(ri.CreateInstance()); private Player loadPlayerFor(RulesetInfo ri) => loadPlayerFor(ri.CreateInstance());
private Player loadPlayerFor(Ruleset r) private Player loadPlayerFor(Ruleset r)
{ {
var beatmap = CreateBeatmap(r); var beatmap = CreateBeatmap(r);
var working = new TestWorkingBeatmap(beatmap);
Beatmap.Value = new TestWorkingBeatmap(beatmap); workingWeakReferences.Add(working);
Beatmap.Value = working;
Beatmap.Value.Mods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) }; Beatmap.Value.Mods.Value = new[] { r.GetAllMods().First(m => m is ModNoFail) };
if (Player != null) Player?.Exit();
Remove(Player);
var player = CreatePlayer(r); var player = CreatePlayer(r);
LoadComponentAsync(player, LoadScreen); playerWeakReferences.Add(player);
LoadComponentAsync(player, p =>
{
Player = p;
LoadScreen(p);
});
return player; return player;
} }