Skip to content

Commit 3ed53ba

Browse files
perf: reduce allocations in beatmap conversion, playable bounds, and HUD components
- BeatmapConverter: replace OrderBy().ToList() with in-place List<T>.Sort() to avoid creating an intermediate IOrderedEnumerable and a second list. - IBeatmap.CalculatePlayableBounds: collapse three separate LINQ enumerations (Any, Max, First) into a single foreach loop. Reduces from O(3n) to O(n) and eliminates two LINQ iterator allocations on every call site. - PausableSkinnableSound.Length: previously evaluated DrawableSamples twice (once for Any(), once for Max()), creating two LINQ chains. Replaced with a single foreach that accumulates the maximum sample length. - JudgementCounter, JudgementCounterDisplay, ArgonJudgementCounter, ArgonJudgementCounterDisplay: replaced Types.First() with direct Types[0] array indexing and removed the now-unused 'using System.Linq' imports. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: winnerspiros <1675249+winnerspiros@users.noreply.github.com>
1 parent 54b20a3 commit 3ed53ba

7 files changed

Lines changed: 36 additions & 15 deletions

File tree

osu.Game/Beatmaps/BeatmapConverter.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,9 @@ protected virtual Beatmap<T> ConvertBeatmap(IBeatmap original, CancellationToken
7070

7171
beatmap.BeatmapInfo = original.BeatmapInfo;
7272
beatmap.ControlPointInfo = original.ControlPointInfo;
73-
beatmap.HitObjects = convertHitObjects(original.HitObjects, original, cancellationToken).OrderBy(s => s.StartTime).ToList();
73+
var hitObjects = convertHitObjects(original.HitObjects, original, cancellationToken);
74+
hitObjects.Sort((a, b) => a.StartTime.CompareTo(b.StartTime));
75+
beatmap.HitObjects = hitObjects;
7476
beatmap.Breaks = original.Breaks;
7577
beatmap.AudioLeadIn = original.AudioLeadIn;
7678
beatmap.StackLeniency = original.StackLeniency;

osu.Game/Beatmaps/IBeatmap.cs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,24 @@ public static double CalculatePlayableLength(IEnumerable<HitObject> objects)
196196
/// </summary>
197197
public static (double start, double end) CalculatePlayableBounds(IEnumerable<HitObject> objects)
198198
{
199-
if (!objects.Any())
200-
return (0, 0);
199+
double firstObjectTime = double.MaxValue;
200+
double lastObjectTime = double.MinValue;
201+
bool any = false;
201202

202-
double lastObjectTime = objects.Max(o => o.GetEndTime());
203-
double firstObjectTime = objects.First().StartTime;
203+
foreach (var obj in objects)
204+
{
205+
any = true;
206+
207+
if (obj.StartTime < firstObjectTime)
208+
firstObjectTime = obj.StartTime;
209+
210+
double endTime = obj.GetEndTime();
211+
212+
if (endTime > lastObjectTime)
213+
lastObjectTime = endTime;
214+
}
204215

205-
return (firstObjectTime, lastObjectTime);
216+
return any ? (firstObjectTime, lastObjectTime) : (0, 0);
206217
}
207218

208219
#endregion

osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCounter.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
22
// See the LICENCE file in the repository root for full licence text.
33

4-
using System.Linq;
54
using osu.Framework.Allocation;
65
using osu.Framework.Bindables;
76
using osu.Framework.Graphics;
@@ -52,7 +51,7 @@ private void load(OsuColour colours)
5251
}
5352
};
5453

55-
var result = Result.Types.First();
54+
var result = Result.Types[0];
5655

5756
Colour = result.IsBasic() ? colours.ForHitResult(result) : !result.IsBonus() ? colours.PurpleLight : colours.PurpleLighter;
5857
}

osu.Game/Screens/Play/HUD/JudgementCounter/JudgementCounterDisplay.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// See the LICENCE file in the repository root for full licence text.
33

44
using System;
5-
using System.Linq;
65
using osu.Framework.Allocation;
76
using osu.Framework.Bindables;
87
using osu.Framework.Graphics;
@@ -89,7 +88,7 @@ bool shouldShow(int index, JudgementCounter counter)
8988
if (index == 0 && !ShowMaxJudgement.Value)
9089
return false;
9190

92-
var hitResult = counter.Result.Types.First();
91+
var hitResult = counter.Result.Types[0];
9392

9493
switch (Mode.Value)
9594
{

osu.Game/Skinning/Components/ArgonJudgementCounter.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
// See the LICENCE file in the repository root for full licence text.
33

44
using System;
5-
using System.Linq;
65
using osu.Framework.Allocation;
76
using osu.Framework.Bindables;
87
using osu.Framework.Extensions.LocalisationExtensions;
@@ -57,7 +56,7 @@ protected override void LoadComplete()
5756
updateWireframe();
5857
}, true);
5958

60-
var result = Result.Types.First();
59+
var result = Result.Types[0];
6160
textComponent.LabelColour.Value = getJudgementColor(result);
6261
textComponent.ShowLabel.BindValueChanged(v => textComponent.TextColour.Value = !v.NewValue ? getJudgementColor(result) : Colour4.White, true);
6362
}

osu.Game/Skinning/Components/ArgonJudgementCounterDisplay.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ private bool shouldBeVisible(int index, ArgonJudgementCounter counter)
117117
if (index == 0 && !ShowMaxJudgement.Value)
118118
return false;
119119

120-
var hitResult = counter.Result.Types.First();
120+
var hitResult = counter.Result.Types[0];
121121

122122
switch (Mode.Value)
123123
{

osu.Game/Skinning/PausableSkinnableSound.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
#nullable disable
55

6+
using System;
67
using System.Collections.Generic;
7-
using System.Linq;
88
using JetBrains.Annotations;
99
using osu.Framework.Allocation;
1010
using osu.Framework.Bindables;
@@ -15,7 +15,18 @@ namespace osu.Game.Skinning
1515
{
1616
public partial class PausableSkinnableSound : SkinnableSound
1717
{
18-
public double Length => !DrawableSamples.Any() ? 0 : DrawableSamples.Max(sample => sample.Length);
18+
public double Length
19+
{
20+
get
21+
{
22+
double max = 0;
23+
24+
foreach (var sample in DrawableSamples)
25+
max = Math.Max(max, sample.Length);
26+
27+
return max;
28+
}
29+
}
1930

2031
public bool RequestedPlaying { get; private set; }
2132

0 commit comments

Comments
 (0)