Merge pull request #26863 from EVAST9919/scrolling-alloc

Further reduce allocation overhead in `ScrollingHitObjectContainer`
This commit is contained in:
Dan Balasescu 2024-02-06 15:57:31 +09:00 committed by GitHub
commit ca36919f10
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 20 additions and 8 deletions

View File

@ -75,8 +75,10 @@ namespace osu.Game.Rulesets.Osu.Mods
{
double time = playfield.Time.Current;
foreach (var drawable in playfield.HitObjectContainer.AliveObjects)
foreach (var entry in playfield.HitObjectContainer.AliveEntries)
{
var drawable = entry.Value;
switch (drawable)
{
case DrawableHitCircle circle:

View File

@ -49,8 +49,10 @@ namespace osu.Game.Rulesets.Osu.Mods
{
var cursorPos = playfield.Cursor.AsNonNull().ActiveCursor.DrawPosition;
foreach (var drawable in playfield.HitObjectContainer.AliveObjects)
foreach (var entry in playfield.HitObjectContainer.AliveEntries)
{
var drawable = entry.Value;
switch (drawable)
{
case DrawableHitCircle circle:

View File

@ -48,8 +48,10 @@ namespace osu.Game.Rulesets.Osu.Mods
{
var cursorPos = playfield.Cursor.AsNonNull().ActiveCursor.DrawPosition;
foreach (var drawable in playfield.HitObjectContainer.AliveObjects)
foreach (var entry in playfield.HitObjectContainer.AliveEntries)
{
var drawable = entry.Value;
var destination = Vector2.Clamp(2 * drawable.Position - cursorPos, Vector2.Zero, OsuPlayfield.BASE_SIZE);
if (drawable.HitObject is Slider thisSlider)

View File

@ -4,9 +4,11 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using osu.Framework.Extensions.ListExtensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Performance;
using osu.Framework.Lists;
namespace osu.Game.Rulesets.Objects.Pooling
{
@ -35,7 +37,7 @@ namespace osu.Game.Rulesets.Objects.Pooling
/// <remarks>
/// The enumeration order is undefined.
/// </remarks>
public IEnumerable<(TEntry Entry, TDrawable Drawable)> AliveEntries => aliveDrawableMap.Select(x => (x.Key, x.Value));
public readonly SlimReadOnlyDictionaryWrapper<TEntry, TDrawable> AliveEntries;
/// <summary>
/// Whether to remove an entry when clock goes backward and crossed its <see cref="LifetimeEntry.LifetimeStart"/>.
@ -63,6 +65,8 @@ namespace osu.Game.Rulesets.Objects.Pooling
lifetimeManager.EntryBecameAlive += entryBecameAlive;
lifetimeManager.EntryBecameDead += entryBecameDead;
lifetimeManager.EntryCrossedBoundary += entryCrossedBoundary;
AliveEntries = aliveDrawableMap.AsSlimReadOnly();
}
/// <summary>

View File

@ -105,7 +105,7 @@ namespace osu.Game.Rulesets.UI
// If required, we can make this lookup more efficient by adding support to get next-future-entry in LifetimeEntryManager.
var candidate =
// Use alive entries first as an optimisation.
hitObjectContainer.AliveEntries.Select(tuple => tuple.Entry).Where(e => !isAlreadyHit(e)).MinBy(e => e.HitObject.StartTime)
hitObjectContainer.AliveEntries.Keys.Where(e => !isAlreadyHit(e)).MinBy(e => e.HitObject.StartTime)
?? hitObjectContainer.Entries.Where(e => !isAlreadyHit(e)).MinBy(e => e.HitObject.StartTime);
// In the case there are no non-judged objects, the last hit object should be used instead.

View File

@ -21,7 +21,7 @@ namespace osu.Game.Rulesets.UI
{
public IEnumerable<DrawableHitObject> Objects => InternalChildren.Cast<DrawableHitObject>().OrderBy(h => h.HitObject.StartTime);
public IEnumerable<DrawableHitObject> AliveObjects => AliveEntries.Select(pair => pair.Drawable).OrderBy(h => h.HitObject.StartTime);
public IEnumerable<DrawableHitObject> AliveObjects => AliveEntries.Values.OrderBy(h => h.HitObject.StartTime);
/// <summary>
/// Invoked when a <see cref="DrawableHitObject"/> is judged.

View File

@ -188,7 +188,7 @@ namespace osu.Game.Rulesets.UI.Scrolling
// We are not using AliveObjects directly to avoid selection/sorting overhead since we don't care about the order at which positions will be updated.
foreach (var entry in AliveEntries)
{
var obj = entry.Drawable;
var obj = entry.Value;
updatePosition(obj, Time.Current);

View File

@ -198,8 +198,10 @@ namespace osu.Game.Screens.Play
foreach (var nested in playfield.NestedPlayfields)
applyToPlayfield(nested);
foreach (DrawableHitObject obj in playfield.HitObjectContainer.AliveObjects)
foreach (var entry in playfield.HitObjectContainer.AliveEntries)
{
var obj = entry.Value;
if (appliedObjects.Contains(obj))
continue;