Skip to content
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

Improve performance of UR calculations #30868

Merged
merged 8 commits into from
Nov 26, 2024
Merged

Improve performance of UR calculations #30868

merged 8 commits into from
Nov 26, 2024

Conversation

peppy
Copy link
Member

@peppy peppy commented Nov 25, 2024

Closes #30635.

Baseline:

Method Mean Error StdDev Allocated
CalculateUnstableRate 15.15 us 0.123 us 0.115 us 96 B

With patch applied (605fe71):

Method Mean Error StdDev Allocated
CalculateUnstableRate 11.30 us 0.064 us 0.060 us 96 B

Didn't show as much of an improvement as I expected to see based on the profiler results (seems like profiler is getting the point of usage slightly wrong...)

With list for iteration (33d725e with foreach switched to for):

Method Mean Error StdDev Allocated
CalculateUnstableRate 9.917 us 0.1824 us 0.1706 us 48 B

Full PR:

Method Mean Error StdDev Allocated
CalculateUnstableRate 25,305.35 us 417.166 us 348.352 us 81943 B
CalculateUnstableRateUsingIncrementalCalculation 24.46 us 0.483 us 0.537 us 40 B

I'm not immediately sure why it's benchmarking slower. Spent my allocated time on this so I'm going just going to smile and nod, but interested if anyone has an idea.

Importantly though, real world performance is much better (over a single autoplay run of this beatmap):

Baseline:

JetBrains Rider 2024-11-25 at 12 00 17

On ea68d4b:

JetBrains Rider 2024-11-25 at 11 58 27

On bbe8f2e (kinda OP because slider ticks and what not will not recalc at all):

JetBrains Rider 2024-11-25 at 12 03 36

public static bool AffectsUnstableRate(HitEvent e) => AffectsUnstableRate(e.HitObject, e.Result);
public static bool AffectsUnstableRate(HitObject hitObject, HitResult result) => hitObject.HitWindows != HitWindows.Empty && result.IsHit();

public class UnstableRateCalculationResult
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sure people are going to want changes to this, but I'm not sure how strict review will be so I've just left it without any safeties initially.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rename NextProcessableIndex to EventCount probably (with the necessary off-by-one adjustments) but otherwise I'm not sure I have much of a problem with this...?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually doesn't require off-by-one adjustments since it already kinda is the event count (at least post-loop-execution).

Copy link
Collaborator

@bdach bdach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't checked very closely but seems mostly fine - cursory review because description gives impression of not being 100% set in stone yet

public static bool AffectsUnstableRate(HitEvent e) => AffectsUnstableRate(e.HitObject, e.Result);
public static bool AffectsUnstableRate(HitObject hitObject, HitResult result) => hitObject.HitWindows != HitWindows.Empty && result.IsHit();

public class UnstableRateCalculationResult
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rename NextProcessableIndex to EventCount probably (with the necessary off-by-one adjustments) but otherwise I'm not sure I have much of a problem with this...?

@peppy
Copy link
Member Author

peppy commented Nov 26, 2024

cursory review because description gives impression of not being 100% set in stone yet

originally i wasn't going to PR, so it probably reads a bit that way. the stand-alone benchmark wasn't giving great improvements.

i'll take a second look at the benchmark today to see if i'm doing anything obviously wrong.

@peppy
Copy link
Member Author

peppy commented Nov 26, 2024

I think it's probably fine as is.

/// The optimisations used here rely on hit events being a consecutive sequence from a single gameplay session.
/// When a new gameplay session is started, any existing results should be disposed.
/// </remarks>
public class UnstableRateCalculationResult
Copy link
Contributor

@smoogipoo smoogipoo Nov 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only query is why this isn't a struct with readonly fields. Perhaps a readonly record struct even.

Minor nitpick, though.

Copy link
Member Author

@peppy peppy Nov 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can try a struct, but as a record the alloc overhead (cpu, not memory) outweighted the benefits, seemingly (see ea68d4b).

But maybe this was just local to the benchmark and not relevant in real-world scenarios.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it has a significant overhead, I'd say leave it then.

Copy link
Contributor

@smoogipoo smoogipoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@smoogipoo smoogipoo requested a review from bdach November 26, 2024 06:39
@bdach bdach merged commit 3e373ae into ppy:master Nov 26, 2024
9 of 10 checks passed
@peppy peppy deleted the ur-perf-fix branch November 27, 2024 03:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Progressively worse stuttering from UR counter with very high note count maps
3 participants