Merge pull request #27173 from EVAST9919/song-select-sort

Reduce allocations during aggregate beatmap sorts in song-select screen
This commit is contained in:
Dean Herbert 2024-02-15 12:50:16 +08:00 committed by GitHub
commit 728f65b6d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 38 additions and 8 deletions

View File

@ -91,19 +91,19 @@ namespace osu.Game.Screens.Select.Carousel
break;
case SortMode.LastPlayed:
comparison = -compareUsingAggregateMax(otherSet, b => (b.LastPlayed ?? DateTimeOffset.MinValue).ToUnixTimeSeconds());
comparison = -compareUsingAggregateMax(otherSet, static b => (b.LastPlayed ?? DateTimeOffset.MinValue).ToUnixTimeSeconds());
break;
case SortMode.BPM:
comparison = compareUsingAggregateMax(otherSet, b => b.BPM);
comparison = compareUsingAggregateMax(otherSet, static b => b.BPM);
break;
case SortMode.Length:
comparison = compareUsingAggregateMax(otherSet, b => b.Length);
comparison = compareUsingAggregateMax(otherSet, static b => b.Length);
break;
case SortMode.Difficulty:
comparison = compareUsingAggregateMax(otherSet, b => b.StarRating);
comparison = compareUsingAggregateMax(otherSet, static b => b.StarRating);
break;
case SortMode.DateSubmitted:
@ -127,12 +127,40 @@ namespace osu.Game.Screens.Select.Carousel
/// <summary>
/// All beatmaps which are not filtered and valid for display.
/// </summary>
protected IEnumerable<BeatmapInfo> ValidBeatmaps => Beatmaps.Where(b => !b.Filtered.Value || b.State.Value == CarouselItemState.Selected).Select(b => b.BeatmapInfo);
protected IEnumerable<BeatmapInfo> ValidBeatmaps
{
get
{
foreach (var item in Items) // iterating over Items directly to not allocate 2 enumerators
{
if (item is CarouselBeatmap b && (!b.Filtered.Value || b.State.Value == CarouselItemState.Selected))
yield return b.BeatmapInfo;
}
}
}
/// <summary>
/// Whether there are available beatmaps which are not filtered and valid for display.
/// Cheaper alternative to <see cref="ValidBeatmaps"/>.Any()
/// </summary>
public bool HasValidBeatmaps
{
get
{
foreach (var item in Items) // iterating over Items directly to not allocate 2 enumerators
{
if (item is CarouselBeatmap b && (!b.Filtered.Value || b.State.Value == CarouselItemState.Selected))
return true;
}
return false;
}
}
private int compareUsingAggregateMax(CarouselBeatmapSet other, Func<BeatmapInfo, double> func)
{
bool ourBeatmaps = ValidBeatmaps.Any();
bool otherBeatmaps = other.ValidBeatmaps.Any();
bool ourBeatmaps = HasValidBeatmaps;
bool otherBeatmaps = other.HasValidBeatmaps;
if (!ourBeatmaps && !otherBeatmaps) return 0;
if (!ourBeatmaps) return -1;

View File

@ -2,6 +2,8 @@
// See the LICENCE file in the repository root for full licence text.
using System.Collections.Generic;
using osu.Framework.Extensions.ListExtensions;
using osu.Framework.Lists;
namespace osu.Game.Screens.Select.Carousel
{
@ -12,7 +14,7 @@ namespace osu.Game.Screens.Select.Carousel
{
public override DrawableCarouselItem? CreateDrawableRepresentation() => null;
public IReadOnlyList<CarouselItem> Items => items;
public SlimReadOnlyListWrapper<CarouselItem> Items => items.AsSlimReadOnly();
public int TotalItemsNotFiltered { get; private set; }