From 071ba5c1dfbf785d45a12713bf3a2d3d3121a710 Mon Sep 17 00:00:00 2001
From: Dean Herbert <pe@ppy.sh>
Date: Tue, 1 Mar 2022 18:28:53 +0900
Subject: [PATCH] Make writes asynchronously to avoid synchronous overhead

---
 .../PlayerSettings/BeatmapOffsetControl.cs    | 29 +++++++++++++++----
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs b/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs
index 75f8c89d34..2f2d1b81e5 100644
--- a/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs
+++ b/osu.Game/Screens/Play/PlayerSettings/BeatmapOffsetControl.cs
@@ -1,8 +1,10 @@
 // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
 // See the LICENCE file in the repository root for full licence text.
 
+using System.Threading.Tasks;
 using osu.Framework.Allocation;
 using osu.Framework.Bindables;
+using osu.Framework.Extensions;
 using osu.Framework.Graphics;
 using osu.Framework.Graphics.Containers;
 using osu.Game.Beatmaps;
@@ -78,9 +80,11 @@ namespace osu.Game.Screens.Play.PlayerSettings
             ReferenceScore.BindValueChanged(scoreChanged, true);
 
             Current.BindValueChanged(currentChanged);
-            Current.Value = realm.Run(r => r.Find<BeatmapInfo>(beatmap.Value.BeatmapInfo.ID).UserSettings?.Offset) ?? 0;
+            Current.Value = realm.Run(r => r.Find<BeatmapInfo>(beatmap.Value.BeatmapInfo.ID).UserSettings.Offset);
         }
 
+        private Task realmWrite;
+
         private void currentChanged(ValueChangedEvent<double> offset)
         {
             if (useAverageButton != null)
@@ -88,12 +92,25 @@ namespace osu.Game.Screens.Play.PlayerSettings
                 useAverageButton.Enabled.Value = offset.NewValue != lastPlayAverage;
             }
 
-            realm.Write(r =>
-            {
-                var settings = r.Find<BeatmapInfo>(beatmap.Value.BeatmapInfo.ID).UserSettings;
+            Scheduler.AddOnce(updateOffset);
 
-                settings.Offset = offset.NewValue;
-            });
+            void updateOffset()
+            {
+                // ensure the previous write has completed.
+                if (realmWrite?.IsCompleted == false)
+                {
+                    Scheduler.AddOnce(updateOffset);
+                    return;
+                }
+
+                realmWrite?.WaitSafely();
+                realmWrite = realm.WriteAsync(r =>
+                {
+                    var settings = r.Find<BeatmapInfo>(beatmap.Value.BeatmapInfo.ID).UserSettings;
+
+                    settings.Offset = offset.NewValue;
+                });
+            }
         }
 
         private void scoreChanged(ValueChangedEvent<ScoreInfo> score)