-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Timed Difficulty Attributes calculation optimization #29482
base: master
Are you sure you want to change the base?
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
protected static void InsertElementInReverseSortedList(List<double> list, double element) | ||
{ | ||
int indexToInsert = list.BinarySearch(element, new ReverseComparer()); | ||
if (indexToInsert < 0) | ||
indexToInsert = ~indexToInsert; | ||
|
||
list.Insert(indexToInsert, element); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before I go through all of the changes in this file (which, is a lot of code added, just for this use case) - why are things like this being reinvented here? Can you not just use SortedList
or something?
I have a feeling that if you try SortedList
or another proper data structure a lot of the code above might just disappear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using normal List
I have full control over what and when is being sorted. SortedList
is a dictionary with unique keys, what means that it's unsuitable for this task, as strains can have the same value. Some time ago I tried to do it with SortedSet
(what still have the same "uniqueness" issue) and it was slower than normal way.
@tsunyoku probably can give better explanation on this as we discussed this problem with him
This comment was marked as off-topic.
This comment was marked as off-topic.
Huh? Care to elaborate? It looks correct to me. |
This comment was marked as off-topic.
This comment was marked as off-topic.
mania is correct for lazer mechanics. "long notes giving combo without judgements" is a stable thing we didn't reimplement. |
This comment was marked as off-topic.
This comment was marked as off-topic.
It already does though? osu/osu.Game.Rulesets.Mania/Difficulty/ManiaDifficultyCalculator.cs Lines 62 to 68 in ebff2eb
|
This comment was marked as off-topic.
This comment was marked as off-topic.
That may well be true but that entire conversation is out of scope of this pull which is supposed to be an "optimisation". I'd advise to move it elsewhere. |
okay I agree |
Timed Difficulty Attributes used for pp counter, and it's very slow on long maps because of O(n^2 * logn) time complexity
Test on full Because Maybe mapset (https://osu.ppy.sh/beatmapsets/773014#osu/2151273). Out of 152 seconds of main function call:
Out of 68 seconds of OsuStrainSkill.DifficultyValue():
After the optimization - out of 13 seconds (-91%) of main function call:
Out of 10 seconds of OsuStrainSkill.DifficultyValue():
Optimization consists of two parts:
First part makes Max Combo and Objects Counts to be calculated progressively in the
ProgressiveBeatmap
beatmap class instead of from zero each time, reducing time complexity from O(n^2) to O(n).Second part is all about
.DifficultyValue()
:After the call of
DifficultyValue()
the sorted strains are saved in the Skill class. On the next call ofDifficultyValue
one of 4 things can happen:Those steps are reducing sort time complexity from O(n^2 * logn) to O(nlogn). Copying time complexity remains O(n^2), making it the slowest part of the calculation now.
The second sort after diffspike nerf is also changed. Unnecessary copy was removed and sorting is done via insertions now, decreasing O(n^2) for copy and O(n^2 * logn) for sort to just O(nlogn) for insertion.
Before:
osu.2024-08-17.16-19-52-155.1.mp4
After:
osu.2024-08-17.16-45-28-019.1.mp4
The other gamemodes aren't touched directly, but as they all use
StrainSkill
- they will be faster as well. Taiko needs additional work, as it's still haveTaikoDifficultyCalculator.combinedDifficultyValue
with O(n^2 * logn) time complexity.