From 48287459a0aa6136e711eb7bc07df187338a7876 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 5 Dec 2019 01:52:22 +0900 Subject: [PATCH] Optimise filters to avoid property retrieval Also reduces number of instantiations of SearchableTerms array in the case of multiple criteria terms. --- .../Select/Carousel/CarouselBeatmap.cs | 32 ++++++++++--------- osu.Game/Screens/Select/FilterCriteria.cs | 6 +++- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs index afd6211dec..68a6ad8845 100644 --- a/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs +++ b/osu.Game/Screens/Select/Carousel/CarouselBeatmap.cs @@ -2,6 +2,7 @@ // See the LICENCE file in the repository root for full licence text. using System; +using System.Collections.Generic; using System.Linq; using osu.Game.Beatmaps; using osu.Game.Screens.Select.Filter; @@ -29,28 +30,29 @@ public override void Filter(FilterCriteria criteria) Beatmap.RulesetID == criteria.Ruleset.ID || (Beatmap.RulesetID == 0 && criteria.Ruleset.ID > 0 && criteria.AllowConvertedBeatmaps); - match &= criteria.StarDifficulty.IsInRange(Beatmap.StarDifficulty); - match &= criteria.ApproachRate.IsInRange(Beatmap.BaseDifficulty.ApproachRate); - match &= criteria.DrainRate.IsInRange(Beatmap.BaseDifficulty.DrainRate); - match &= criteria.CircleSize.IsInRange(Beatmap.BaseDifficulty.CircleSize); - match &= criteria.Length.IsInRange(Beatmap.Length); - match &= criteria.BPM.IsInRange(Beatmap.BPM); + match &= !criteria.StarDifficulty.HasFilter || criteria.StarDifficulty.IsInRange(Beatmap.StarDifficulty); + match &= !criteria.ApproachRate.HasFilter || criteria.ApproachRate.IsInRange(Beatmap.BaseDifficulty.ApproachRate); + match &= !criteria.DrainRate.HasFilter || criteria.DrainRate.IsInRange(Beatmap.BaseDifficulty.DrainRate); + match &= !criteria.CircleSize.HasFilter || criteria.CircleSize.IsInRange(Beatmap.BaseDifficulty.CircleSize); + match &= !criteria.Length.HasFilter || criteria.Length.IsInRange(Beatmap.Length); + match &= !criteria.BPM.HasFilter || criteria.BPM.IsInRange(Beatmap.BPM); - match &= criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor); - match &= criteria.OnlineStatus.IsInRange(Beatmap.Status); + match &= !criteria.BeatDivisor.HasFilter || criteria.BeatDivisor.IsInRange(Beatmap.BeatDivisor); + match &= !criteria.OnlineStatus.HasFilter || criteria.OnlineStatus.IsInRange(Beatmap.Status); - match &= criteria.Creator.Matches(Beatmap.Metadata.AuthorString); - match &= criteria.Artist.Matches(Beatmap.Metadata.Artist) || + match &= !criteria.Creator.HasFilter || criteria.Creator.Matches(Beatmap.Metadata.AuthorString); + match &= !criteria.Artist.HasFilter || criteria.Artist.Matches(Beatmap.Metadata.Artist) || criteria.Artist.Matches(Beatmap.Metadata.ArtistUnicode); if (match) { + var terms = new List(); + + terms.AddRange(Beatmap.Metadata.SearchableTerms); + terms.Add(Beatmap.Version); + foreach (var criteriaTerm in criteria.SearchTerms) - { - match &= - Beatmap.Metadata.SearchableTerms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0) || - Beatmap.Version.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0; - } + match &= terms.Any(term => term.IndexOf(criteriaTerm, StringComparison.InvariantCultureIgnoreCase) >= 0); } Filtered.Value = !match; diff --git a/osu.Game/Screens/Select/FilterCriteria.cs b/osu.Game/Screens/Select/FilterCriteria.cs index 7971506fa3..abcb1f2171 100644 --- a/osu.Game/Screens/Select/FilterCriteria.cs +++ b/osu.Game/Screens/Select/FilterCriteria.cs @@ -46,6 +46,8 @@ public string SearchText public struct OptionalRange : IEquatable> where T : struct, IComparable { + public bool HasFilter => Max != null || Min != null; + public bool IsInRange(T value) { if (Min != null) @@ -87,9 +89,11 @@ public bool Equals(OptionalRange other) public struct OptionalTextFilter : IEquatable { + public bool HasFilter => !string.IsNullOrEmpty(SearchTerm); + public bool Matches(string value) { - if (string.IsNullOrEmpty(SearchTerm)) + if (!HasFilter) return true; // search term is guaranteed to be non-empty, so if the string we're comparing is empty, it's not matching