From 2dd99ef1fdc835fd14297371a159d94af8f7c9d0 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 25 Jul 2022 16:26:47 +0900 Subject: [PATCH] Refactor `FPSCounter` to not use scheduled tasks While on the surface this looks harmless (ignoring allocations), `Scheduler` doesn't clear cancelled tasks until they reach their execution time. This can cause an increase in time spent processing the scheduler itself. I don't think a per-frame updating component should use scheduled tasks in this way in the first place, so I've just rewritten the logic to avoid that overhead altogether. --- osu.Game/Graphics/UserInterface/FPSCounter.cs | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/osu.Game/Graphics/UserInterface/FPSCounter.cs b/osu.Game/Graphics/UserInterface/FPSCounter.cs index 6fa53b32d8..539ac7ed1f 100644 --- a/osu.Game/Graphics/UserInterface/FPSCounter.cs +++ b/osu.Game/Graphics/UserInterface/FPSCounter.cs @@ -11,7 +11,6 @@ using osu.Framework.Graphics.Cursor; using osu.Framework.Graphics.Shapes; using osu.Framework.Input.Events; using osu.Framework.Platform; -using osu.Framework.Threading; using osu.Framework.Timing; using osu.Framework.Utils; using osu.Game.Configuration; @@ -44,8 +43,6 @@ namespace osu.Game.Graphics.UserInterface private bool isDisplayed; - private ScheduledDelegate? fadeOutDelegate; - private double aimDrawFPS; private double aimUpdateFPS; @@ -54,6 +51,11 @@ namespace osu.Game.Graphics.UserInterface private ThrottledFrameClock updateClock = null!; private ThrottledFrameClock inputClock = null!; + /// + /// The last time value where the display was required (due to a significant change or hovering). + /// + private double lastDisplayRequiredTime; + [Resolved] private OsuColour colours { get; set; } = null!; @@ -131,13 +133,13 @@ namespace osu.Game.Graphics.UserInterface { base.LoadComplete(); - displayTemporarily(); + requestDisplay(); showFpsDisplay.BindValueChanged(showFps => { State.Value = showFps.NewValue ? Visibility.Visible : Visibility.Hidden; if (showFps.NewValue) - displayTemporarily(); + requestDisplay(); }, true); State.BindValueChanged(state => showFpsDisplay.Value = state.NewValue == Visibility.Visible); @@ -150,38 +152,17 @@ namespace osu.Game.Graphics.UserInterface protected override bool OnHover(HoverEvent e) { background.FadeTo(1, 200); - displayTemporarily(); + requestDisplay(); return base.OnHover(e); } protected override void OnHoverLost(HoverLostEvent e) { background.FadeTo(idle_background_alpha, 200); - displayTemporarily(); + requestDisplay(); base.OnHoverLost(e); } - private void displayTemporarily() - { - if (!isDisplayed) - { - mainContent.FadeTo(1, 300, Easing.OutQuint); - isDisplayed = true; - } - - fadeOutDelegate?.Cancel(); - fadeOutDelegate = null; - - if (!IsHovered) - { - fadeOutDelegate = Scheduler.AddDelayed(() => - { - mainContent.FadeTo(0, 300, Easing.OutQuint); - isDisplayed = false; - }, 2000); - } - } - protected override void Update() { base.Update(); @@ -221,7 +202,23 @@ namespace osu.Game.Graphics.UserInterface || 1000 / displayedFrameTime < aimUpdateFPS * 0.8; if (hasSignificantChanges) - displayTemporarily(); + requestDisplay(); + else if (isDisplayed && Time.Current - lastDisplayRequiredTime > 2000) + { + mainContent.FadeTo(0, 300, Easing.OutQuint); + isDisplayed = false; + } + } + + private void requestDisplay() + { + lastDisplayRequiredTime = Time.Current; + + if (!isDisplayed) + { + mainContent.FadeTo(1, 300, Easing.OutQuint); + isDisplayed = true; + } } private void updateFpsDisplay()