This PR optimizes accelerates various components of ChroMapper by taking advantage of Span<T>. Iterating over a Span<T> is noticeably faster, even when compared to iterating a List<T> using a for loop. In addition, Span<T> iteration does not allocate memory, unlike a foreach loop.
Made possible by UnityH4xx, a Unity library that uses custom written IL to expose the backing array of a List<T> as a Span<T>. This is official API in .NET 5 and later, but is unfortunately left out of .NET Standard 2.1.
BeatmapObjectCallbackController<T>.RefreshPool is almost entirely rewritten, not only to utilize Span<T> but also using Binary Search to reduce the average runtime from O(n) to O(log n).
Pausing, unpausing, and scrolling through any object-heavy level should see noticeable improvements.
EnumerableExtensions methods now take advantage of Span<T>.
BeatmapObjectCallbackController<T>.GetViewBetween is now Span<T> accelerated, providing a direct view into the MapObjects list rather than allocating an entirely new collection.
CustomEventsGridContainer now uses Span<T> iteration when it previously used for/foreach iteration
RotationCallbackController sees similar accelerations by using both Span<T> and Binary Search
Pausing, unpausing, and scrolling through 360/90 levels dense with rotations should see additional improvements.
MapLoader uses Span<T> to quickly recalculate song bpm time
Strobe Generator has been touched a little bit, being slightly more memory efficient by using the Span<T>-backed GetViewBetween
However, Strobe Generator itself is still largely inefficient thanks to heavy LINQ abuse. It deserves a proper rewrite in due time.
While a little out of PR scope, GridRotationController no longer uses a coroutine to handle 360/90 rotation transitions. This saves some accumulated garbage every frame.
This PR optimizes accelerates various components of ChroMapper by taking advantage of
Span<T>
. Iterating over aSpan<T>
is noticeably faster, even when compared to iterating aList<T>
using afor
loop. In addition,Span<T>
iteration does not allocate memory, unlike aforeach
loop.Made possible by UnityH4xx, a Unity library that uses custom written IL to expose the backing array of a
List<T>
as aSpan<T>
. This is official API in .NET 5 and later, but is unfortunately left out of .NET Standard 2.1.The Only Thing They Fear is You is a good benchmark map if you want to compare performance improvements in this PR.
ChroMapper code that was touched by this PR:
BeatmapObjectCallbackController<T>.RefreshPool
is almost entirely rewritten, not only to utilizeSpan<T>
but also using Binary Search to reduce the average runtime from O(n) to O(log n).EnumerableExtensions
methods now take advantage ofSpan<T>
.BeatmapObjectCallbackController<T>.GetViewBetween
is nowSpan<T>
accelerated, providing a direct view into theMapObjects
list rather than allocating an entirely new collection.CustomEventsGridContainer
now usesSpan<T>
iteration when it previously used for/foreach iterationRotationCallbackController
sees similar accelerations by using bothSpan<T>
and Binary SearchMapLoader
usesSpan<T>
to quickly recalculate song bpm timeSpan<T>
-backedGetViewBetween
GridRotationController
no longer uses a coroutine to handle 360/90 rotation transitions. This saves some accumulated garbage every frame.