Optimise carousel memory usage by unloading off-screen panels

This commit is contained in:
Dean Herbert
2018-09-06 13:27:17 +09:00
parent 9b753bb429
commit e63f60231a
3 changed files with 29 additions and 4 deletions

View File

@ -424,7 +424,7 @@ namespace osu.Game.Screens.Select
float drawHeight = DrawHeight; float drawHeight = DrawHeight;
// Remove all items that should no longer be on-screen // Remove all items that should no longer be on-screen
scrollableContent.RemoveAll(p => p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent); scrollableContent.RemoveAll(p => p.CanBeRemoved && (p.Y < Current - p.DrawHeight || p.Y > Current + drawHeight || !p.IsPresent));
// Find index range of all items that should be on-screen // Find index range of all items that should be on-screen
Trace.Assert(Items.Count == yPositions.Count); Trace.Assert(Items.Count == yPositions.Count);
@ -486,6 +486,15 @@ namespace osu.Game.Screens.Select
updateItem(p, halfHeight); updateItem(p, halfHeight);
} }
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
// aggressively dispose "off-screen" items to reduce GC pressure.
foreach (var i in Items)
i.Dispose();
}
private CarouselBeatmapSet createCarouselSet(BeatmapSetInfo beatmapSet) private CarouselBeatmapSet createCarouselSet(BeatmapSetInfo beatmapSet)
{ {
if (beatmapSet.Beatmaps.All(b => b.Hidden)) if (beatmapSet.Beatmaps.All(b => b.Hidden))

View File

@ -30,6 +30,7 @@ namespace osu.Game.Screens.Select.Carousel
private DialogOverlay dialogOverlay; private DialogOverlay dialogOverlay;
private readonly BeatmapSetInfo beatmapSet; private readonly BeatmapSetInfo beatmapSet;
private DelayedLoadUnloadWrapper delayed;
public DrawableCarouselBeatmapSet(CarouselBeatmapSet set) public DrawableCarouselBeatmapSet(CarouselBeatmapSet set)
: base(set) : base(set)
@ -37,6 +38,10 @@ namespace osu.Game.Screens.Select.Carousel
beatmapSet = set.BeatmapSet; beatmapSet = set.BeatmapSet;
} }
public override bool CanBeRemoved => delayed?.DelayedLoadCompleted != true;
protected override bool RequiresChildrenUpdate => true;
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(LocalisationEngine localisation, BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay) private void load(LocalisationEngine localisation, BeatmapManager manager, BeatmapSetOverlay beatmapOverlay, DialogOverlay overlay)
{ {
@ -50,12 +55,12 @@ namespace osu.Game.Screens.Select.Carousel
Children = new Drawable[] Children = new Drawable[]
{ {
new DelayedLoadWrapper( delayed = new DelayedLoadUnloadWrapper(() =>
new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault())) new PanelBackground(manager.GetWorkingBeatmap(beatmapSet.Beatmaps.FirstOrDefault()))
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
OnLoadComplete = d => d.FadeInFromZero(1000, Easing.OutQuint), OnLoadComplete = d => d.FadeInFromZero(1000, Easing.OutQuint),
}, 300 }, 300, 5000
), ),
new FillFlowContainer new FillFlowContainer
{ {

View File

@ -24,6 +24,11 @@ namespace osu.Game.Screens.Select.Carousel
public override bool IsPresent => base.IsPresent || Item.Visible; public override bool IsPresent => base.IsPresent || Item.Visible;
/// <summary>
/// Whether this item can be removed from the scroll container (usually due to being off-screen).
/// </summary>
public virtual bool CanBeRemoved => true;
public readonly CarouselItem Item; public readonly CarouselItem Item;
private Container nestedContainer; private Container nestedContainer;
@ -86,7 +91,13 @@ namespace osu.Game.Screens.Select.Carousel
base.OnHoverLost(state); base.OnHoverLost(state);
} }
public void SetMultiplicativeAlpha(float alpha) => borderContainer.Alpha = alpha; protected bool VisibleInCarousel;
public void SetMultiplicativeAlpha(float alpha)
{
borderContainer.Alpha = alpha;
VisibleInCarousel = alpha > 0;
}
protected override void LoadComplete() protected override void LoadComplete()
{ {