1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 17:07:38 +08:00

Merge branch 'realm-context-use-update-when-feasible' into fix-intro-realm-usage

This commit is contained in:
Dean Herbert 2022-01-22 16:30:07 +09:00
commit 1a591beb7d
5 changed files with 153 additions and 4 deletions

View File

@ -0,0 +1,141 @@
// 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.Linq;
using System.Threading;
using BenchmarkDotNet.Attributes;
using osu.Framework.Testing;
using osu.Framework.Threading;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Rulesets.Osu;
using osu.Game.Tests.Resources;
namespace osu.Game.Benchmarks
{
public class BenchmarkRealmReads : BenchmarkTest
{
private TemporaryNativeStorage storage;
private RealmContextFactory realmFactory;
private UpdateThread updateThread;
[Params(1, 100, 1000)]
public int ReadsPerFetch { get; set; }
public override void SetUp()
{
storage = new TemporaryNativeStorage("realm-benchmark");
storage.DeleteDirectory(string.Empty);
realmFactory = new RealmContextFactory(storage, "client");
realmFactory.Run(realm =>
{
realm.Write(c => c.Add(TestResources.CreateTestBeatmapSetInfo(rulesets: new[] { new OsuRuleset().RulesetInfo })));
});
updateThread = new UpdateThread(() => { }, null);
updateThread.Start();
}
[Benchmark]
public void BenchmarkDirectPropertyRead()
{
realmFactory.Run(realm =>
{
var beatmapSet = realm.All<BeatmapSetInfo>().First();
for (int i = 0; i < ReadsPerFetch; i++)
{
string _ = beatmapSet.Beatmaps.First().Hash;
}
});
}
[Benchmark]
public void BenchmarkDirectPropertyReadUpdateThread()
{
var done = new ManualResetEventSlim();
updateThread.Scheduler.Add(() =>
{
try
{
var beatmapSet = realmFactory.Context.All<BeatmapSetInfo>().First();
for (int i = 0; i < ReadsPerFetch; i++)
{
string _ = beatmapSet.Beatmaps.First().Hash;
}
}
finally
{
done.Set();
}
});
done.Wait();
}
[Benchmark]
public void BenchmarkRealmLivePropertyRead()
{
realmFactory.Run(realm =>
{
var beatmapSet = realm.All<BeatmapSetInfo>().First().ToLive(realmFactory);
for (int i = 0; i < ReadsPerFetch; i++)
{
string _ = beatmapSet.PerformRead(b => b.Beatmaps.First().Hash);
}
});
}
[Benchmark]
public void BenchmarkRealmLivePropertyReadUpdateThread()
{
var done = new ManualResetEventSlim();
updateThread.Scheduler.Add(() =>
{
try
{
var beatmapSet = realmFactory.Context.All<BeatmapSetInfo>().First().ToLive(realmFactory);
for (int i = 0; i < ReadsPerFetch; i++)
{
string _ = beatmapSet.PerformRead(b => b.Beatmaps.First().Hash);
}
}
finally
{
done.Set();
}
});
done.Wait();
}
[Benchmark]
public void BenchmarkDetachedPropertyRead()
{
realmFactory.Run(realm =>
{
var beatmapSet = realm.All<BeatmapSetInfo>().First().Detach();
for (int i = 0; i < ReadsPerFetch; i++)
{
string _ = beatmapSet.Beatmaps.First().Hash;
}
});
}
[GlobalCleanup]
public void Cleanup()
{
realmFactory?.Dispose();
storage?.Dispose();
updateThread?.Exit();
}
}
}

View File

@ -47,6 +47,11 @@ namespace osu.Game.Tests.Database
liveBeatmap = beatmap.ToLive(realmFactory);
});
using (realmFactory.BlockAllOperations())
{
// recycle realm before migrating
}
using (var migratedStorage = new TemporaryNativeStorage("realm-test-migration-target"))
{
migratedStorage.DeleteDirectory(string.Empty);

View File

@ -72,7 +72,7 @@ namespace osu.Game.Database
get
{
if (!ThreadSafety.IsUpdateThread)
throw new InvalidOperationException(@$"Use {nameof(createContext)} when performing realm operations from a non-update thread");
throw new InvalidOperationException(@$"Use {nameof(Run)}/{nameof(Write)} when performing realm operations from a non-update thread");
lock (contextLock)
{

View File

@ -21,6 +21,9 @@ namespace osu.Game.Database
/// <param name="data">The realm data.</param>
public RealmLiveUnmanaged(T data)
{
if (data.IsManaged)
throw new InvalidOperationException($"Cannot use {nameof(RealmLiveUnmanaged<T>)} with managed instances");
Value = data;
}

View File

@ -34,9 +34,9 @@ namespace osu.Game.Overlays.Settings.Sections.Input
{
string rulesetName = Ruleset?.ShortName;
List<RealmKeyBinding> bindings = null;
realmFactory.Run(realm => bindings = realm.All<RealmKeyBinding>().Where(b => b.RulesetName == rulesetName && b.Variant == variant).Detach());
var bindings = realmFactory.Run(realm => realm.All<RealmKeyBinding>()
.Where(b => b.RulesetName == rulesetName && b.Variant == variant)
.Detach());
foreach (var defaultGroup in Defaults.GroupBy(d => d.Action))
{