mirror of
https://github.com/ppy/osu.git
synced 2026-05-29 02:29:54 +08:00
Add debounce to difficulty calculation operations in churn scenarios
This commit is contained in:
@@ -141,7 +141,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<StarDifficulty?> GetDifficultyAsync(IBeatmapInfo beatmapInfo, IRulesetInfo? rulesetInfo = null, IEnumerable<Mod>? mods = null, CancellationToken cancellationToken = default)
|
||||
public override async Task<StarDifficulty?> GetDifficultyAsync(IBeatmapInfo beatmapInfo, IRulesetInfo? rulesetInfo = null, IEnumerable<Mod>? mods = null, CancellationToken cancellationToken = default, int debounceDelay = 0)
|
||||
{
|
||||
if (blockCalculation)
|
||||
{
|
||||
@@ -149,7 +149,7 @@ namespace osu.Game.Tests.Visual.SongSelect
|
||||
await calculationBlocker.Task.ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return await base.GetDifficultyAsync(beatmapInfo, rulesetInfo, mods, cancellationToken).ConfigureAwait(false);
|
||||
return await base.GetDifficultyAsync(beatmapInfo, rulesetInfo, mods, cancellationToken, 0).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +125,7 @@ namespace osu.Game.Tests.Visual.UserInterface
|
||||
public StarDifficulty? Difficulty { get; set; }
|
||||
|
||||
public override Task<StarDifficulty?> GetDifficultyAsync(IBeatmapInfo beatmapInfo, IRulesetInfo? rulesetInfo = null, IEnumerable<Mod>? mods = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
CancellationToken cancellationToken = default, int computationDelay = 0)
|
||||
=> Task.FromResult(Difficulty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,12 +98,13 @@ namespace osu.Game.Beatmaps
|
||||
/// </summary>
|
||||
/// <param name="beatmapInfo">The <see cref="BeatmapInfo"/> to get the difficulty of.</param>
|
||||
/// <param name="cancellationToken">An optional <see cref="CancellationToken"/> which stops updating the star difficulty for the given <see cref="BeatmapInfo"/>.</param>
|
||||
/// <param name="computationDelay">A delay in milliseconds before performing the </param>
|
||||
/// <returns>A bindable that is updated to contain the star difficulty when it becomes available. Will be null while in an initial calculating state (but not during updates to ruleset and mods if a stale value is already propagated).</returns>
|
||||
public IBindable<StarDifficulty?> GetBindableDifficulty(IBeatmapInfo beatmapInfo, CancellationToken cancellationToken = default)
|
||||
public IBindable<StarDifficulty?> GetBindableDifficulty(IBeatmapInfo beatmapInfo, CancellationToken cancellationToken = default, int computationDelay = 0)
|
||||
{
|
||||
var bindable = new BindableStarDifficulty(beatmapInfo, cancellationToken);
|
||||
|
||||
updateBindable(bindable, currentRuleset.Value, currentMods.Value, cancellationToken);
|
||||
updateBindable(bindable, currentRuleset.Value, currentMods.Value, cancellationToken, computationDelay);
|
||||
|
||||
lock (bindableUpdateLock)
|
||||
trackedBindables.Add(bindable);
|
||||
@@ -118,13 +119,14 @@ namespace osu.Game.Beatmaps
|
||||
/// <param name="rulesetInfo">The <see cref="IRulesetInfo"/> to get the difficulty with.</param>
|
||||
/// <param name="mods">The <see cref="Mod"/>s to get the difficulty with.</param>
|
||||
/// <param name="cancellationToken">An optional <see cref="CancellationToken"/> which stops computing the star difficulty.</param>
|
||||
/// <param name="computationDelay">In the case a cached lookup was not possible, a value in milliseconds of to wait until performing potentially intensive lookup.</param>
|
||||
/// <returns>
|
||||
/// The requested <see cref="StarDifficulty"/>, if non-<see langword="null"/>.
|
||||
/// A <see langword="null"/> return value indicates that the difficulty process failed or was interrupted early,
|
||||
/// and as such there is no usable star difficulty value to be returned.
|
||||
/// </returns>
|
||||
public virtual Task<StarDifficulty?> GetDifficultyAsync(IBeatmapInfo beatmapInfo, IRulesetInfo? rulesetInfo = null,
|
||||
IEnumerable<Mod>? mods = null, CancellationToken cancellationToken = default)
|
||||
public virtual Task<StarDifficulty?> GetDifficultyAsync(IBeatmapInfo beatmapInfo, IRulesetInfo? rulesetInfo = null, IEnumerable<Mod>? mods = null,
|
||||
CancellationToken cancellationToken = default, int computationDelay = 0)
|
||||
{
|
||||
// In the case that the user hasn't given us a ruleset, use the beatmap's default ruleset.
|
||||
rulesetInfo ??= beatmapInfo.Ruleset;
|
||||
@@ -139,7 +141,7 @@ namespace osu.Game.Beatmaps
|
||||
return Task.FromResult<StarDifficulty?>(new StarDifficulty(beatmapInfo.StarRating, (beatmapInfo as IBeatmapOnlineInfo)?.MaxCombo ?? 0));
|
||||
}
|
||||
|
||||
return GetAsync(new DifficultyCacheLookup(localBeatmapInfo, localRulesetInfo, mods), cancellationToken);
|
||||
return GetAsync(new DifficultyCacheLookup(localBeatmapInfo, localRulesetInfo, mods), cancellationToken, computationDelay);
|
||||
}
|
||||
|
||||
protected override Task<StarDifficulty?> ComputeValueAsync(DifficultyCacheLookup lookup, CancellationToken cancellationToken = default)
|
||||
@@ -206,11 +208,12 @@ namespace osu.Game.Beatmaps
|
||||
/// <param name="rulesetInfo">The <see cref="IRulesetInfo"/> to update with.</param>
|
||||
/// <param name="mods">The <see cref="Mod"/>s to update with.</param>
|
||||
/// <param name="cancellationToken">A token that may be used to cancel this update.</param>
|
||||
private void updateBindable(BindableStarDifficulty bindable, IRulesetInfo? rulesetInfo, IEnumerable<Mod>? mods, CancellationToken cancellationToken = default)
|
||||
/// <param name="computationDelay">In the case a cached lookup was not possible, a value in milliseconds of to wait until performing potentially intensive lookup.</param>
|
||||
private void updateBindable(BindableStarDifficulty bindable, IRulesetInfo? rulesetInfo, IEnumerable<Mod>? mods, CancellationToken cancellationToken = default, int computationDelay = 0)
|
||||
{
|
||||
// GetDifficultyAsync will fall back to existing data from IBeatmapInfo if not locally available
|
||||
// (contrary to GetAsync)
|
||||
GetDifficultyAsync(bindable.BeatmapInfo, rulesetInfo, mods, cancellationToken)
|
||||
GetDifficultyAsync(bindable.BeatmapInfo, rulesetInfo, mods, cancellationToken, computationDelay)
|
||||
.ContinueWith(task =>
|
||||
{
|
||||
// We're on a threadpool thread, but we should exit back to the update thread so consumers can safely handle value-changed events.
|
||||
|
||||
@@ -35,8 +35,9 @@ namespace osu.Game.Database
|
||||
/// Retrieve the cached value for the given lookup.
|
||||
/// </summary>
|
||||
/// <param name="lookup">The lookup to retrieve.</param>
|
||||
/// <param name="token">An optional <see cref="CancellationToken"/> to cancel the operation.</param>
|
||||
protected async Task<TValue?> GetAsync(TLookup lookup, CancellationToken token = default)
|
||||
/// <param name="cancellationToken">An optional <see cref="CancellationToken"/> to cancel the operation.</param>
|
||||
/// <param name="computationDelay">In the case a cached lookup was not possible, a value in milliseconds of to wait until performing potentially intensive lookup.</param>
|
||||
protected async Task<TValue?> GetAsync(TLookup lookup, CancellationToken cancellationToken = default, int computationDelay = 0)
|
||||
{
|
||||
if (CheckExists(lookup, out TValue? existing))
|
||||
{
|
||||
@@ -44,7 +45,10 @@ namespace osu.Game.Database
|
||||
return existing;
|
||||
}
|
||||
|
||||
var computed = await ComputeValueAsync(lookup, token).ConfigureAwait(false);
|
||||
if (computationDelay > 0)
|
||||
await Task.Delay(computationDelay, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var computed = await ComputeValueAsync(lookup, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
statistics.Value.MissCount++;
|
||||
|
||||
|
||||
@@ -246,7 +246,7 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
if (Item?.State.Value != CarouselItemState.Collapsed)
|
||||
{
|
||||
// We've potentially cancelled the computation above so a new bindable is required.
|
||||
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmapInfo, (starDifficultyCancellationSource = new CancellationTokenSource()).Token);
|
||||
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmapInfo, (starDifficultyCancellationSource = new CancellationTokenSource()).Token, 200);
|
||||
starDifficultyBindable.BindValueChanged(d =>
|
||||
{
|
||||
starCounter.Current = (float)(d.NewValue?.Stars ?? 0);
|
||||
|
||||
@@ -202,7 +202,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
|
||||
var beatmap = (BeatmapInfo)Item.Model;
|
||||
|
||||
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmap, starDifficultyCancellationSource.Token);
|
||||
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmap, starDifficultyCancellationSource.Token, 200);
|
||||
starDifficultyBindable.BindValueChanged(_ => updateDisplay(), true);
|
||||
}
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ namespace osu.Game.Screens.SelectV2
|
||||
|
||||
var beatmap = (BeatmapInfo)Item.Model;
|
||||
|
||||
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmap, starDifficultyCancellationSource.Token);
|
||||
starDifficultyBindable = difficultyCache.GetBindableDifficulty(beatmap, starDifficultyCancellationSource.Token, 200);
|
||||
starDifficultyBindable.BindValueChanged(_ => updateDisplay(), true);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user