From df20845fbb170528ad5c8c0d96c8a4d4c73ac991 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Mon, 23 Oct 2017 16:35:35 +0900 Subject: [PATCH] Share one context per file store for performance reasons There is now a CreateContext method for retrieving a stand-alone context for threaded use. We may want to add safety against this context being disposed (or just return a fresh one if it is). --- osu.Game/Database/DatabaseBackedStore.cs | 18 +++++++++++++++--- osu.Game/Database/OsuDbContext.cs | 1 + osu.Game/IO/FileStore.cs | 2 +- osu.Game/Input/KeyBindingStore.cs | 15 +++++++-------- .../Sections/Maintenance/GeneralSettings.cs | 3 ++- 5 files changed, 26 insertions(+), 13 deletions(-) diff --git a/osu.Game/Database/DatabaseBackedStore.cs b/osu.Game/Database/DatabaseBackedStore.cs index be86d35335..35700e90fc 100644 --- a/osu.Game/Database/DatabaseBackedStore.cs +++ b/osu.Game/Database/DatabaseBackedStore.cs @@ -11,12 +11,24 @@ namespace osu.Game.Database { protected readonly Storage Storage; - protected readonly Func GetContext; + /// + /// Create a new instance (separate from the shared context via for performing isolated operations. + /// + protected readonly Func CreateContext; - protected DatabaseBackedStore(Func getContext, Storage storage = null) + private readonly Lazy queryContext; + + /// + /// Retrieve a shared context for performing lookups (or write operations on the update thread, for now). + /// + protected OsuDbContext GetContext() => queryContext.Value; + + protected DatabaseBackedStore(Func createContext, Storage storage = null) { + CreateContext = createContext; + queryContext = new Lazy(CreateContext); + Storage = storage; - GetContext = getContext; try { diff --git a/osu.Game/Database/OsuDbContext.cs b/osu.Game/Database/OsuDbContext.cs index 6c267811a1..0904a5151d 100644 --- a/osu.Game/Database/OsuDbContext.cs +++ b/osu.Game/Database/OsuDbContext.cs @@ -24,6 +24,7 @@ namespace osu.Game.Database public DbSet DatabasedKeyBinding { get; set; } public DbSet FileInfo { get; set; } public DbSet RulesetInfo { get; set; } + private readonly string connectionString; private static readonly Lazy logger = new Lazy(() => new OsuDbLoggerFactory()); diff --git a/osu.Game/IO/FileStore.cs b/osu.Game/IO/FileStore.cs index 6654fa7cb1..b69916e565 100644 --- a/osu.Game/IO/FileStore.cs +++ b/osu.Game/IO/FileStore.cs @@ -22,7 +22,7 @@ namespace osu.Game.IO public Storage Storage => base.Storage; - public FileStore(Func getContext, Storage storage) : base(getContext, storage.GetStorageForDirectory(@"files")) + public FileStore(Func createContext, Storage storage) : base(createContext, storage.GetStorageForDirectory(@"files")) { Store = new StorageBackedResourceStore(Storage); } diff --git a/osu.Game/Input/KeyBindingStore.cs b/osu.Game/Input/KeyBindingStore.cs index 0a0cd3dd6f..1e1b1d74d4 100644 --- a/osu.Game/Input/KeyBindingStore.cs +++ b/osu.Game/Input/KeyBindingStore.cs @@ -17,8 +17,8 @@ namespace osu.Game.Input { public event Action KeyBindingChanged; - public KeyBindingStore(Func getContext, RulesetStore rulesets, Storage storage = null) - : base(getContext, storage) + public KeyBindingStore(Func createContext, RulesetStore rulesets, Storage storage = null) + : base(createContext, storage) { foreach (var info in rulesets.AvailableRulesets) { @@ -38,13 +38,14 @@ namespace osu.Game.Input private void insertDefaults(IEnumerable defaults, int? rulesetId = null, int? variant = null) { - using (var context = GetContext()) + var context = GetContext(); + using (var transaction = context.BeginTransaction()) { // compare counts in database vs defaults foreach (var group in defaults.GroupBy(k => k.Action)) { - int count = query(context, rulesetId, variant).Count(k => (int)k.Action == (int)group.Key); + int count = Query(rulesetId, variant).Count(k => (int)k.Action == (int)group.Key); int aimCount = group.Count(); if (aimCount <= count) @@ -71,10 +72,8 @@ namespace osu.Game.Input /// The ruleset's internal ID. /// An optional variant. /// - public IEnumerable Query(int? rulesetId = null, int? variant = null) => query(GetContext(), rulesetId, variant); - - private IEnumerable query(OsuDbContext context, int? rulesetId = null, int? variant = null) => - context.DatabasedKeyBinding.Where(b => b.RulesetID == rulesetId && b.Variant == variant); + public IEnumerable Query(int? rulesetId = null, int? variant = null) => + GetContext().DatabasedKeyBinding.Where(b => b.RulesetID == rulesetId && b.Variant == variant); public void Update(KeyBinding keyBinding) { diff --git a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs index 233ca7be60..cea070102d 100644 --- a/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs +++ b/osu.Game/Overlays/Settings/Sections/Maintenance/GeneralSettings.cs @@ -1,6 +1,7 @@ // Copyright (c) 2007-2017 ppy Pty Ltd . // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE +using System.Linq; using System.Threading.Tasks; using osu.Framework.Allocation; using osu.Framework.Graphics; @@ -51,7 +52,7 @@ namespace osu.Game.Overlays.Settings.Sections.Maintenance restoreButton.Enabled.Value = false; Task.Run(() => { - foreach (var b in beatmaps.QueryBeatmaps(b => b.Hidden)) + foreach (var b in beatmaps.QueryBeatmaps(b => b.Hidden).ToList()) beatmaps.Restore(b); }).ContinueWith(t => Schedule(() => restoreButton.Enabled.Value = true)); }