From f49b13726980688ad6bd7ec94deb1f515aeca024 Mon Sep 17 00:00:00 2001 From: James Wilson Date: Wed, 17 Apr 2024 19:57:17 +0100 Subject: [PATCH 01/10] refactor `BeatmapStore` to use `MemoryCache` --- .../Stores/BeatmapStore.cs | 67 +++++++++++++------ ...ver.Queues.ScoreStatisticsProcessor.csproj | 1 + 2 files changed, 46 insertions(+), 22 deletions(-) diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs index 9cf1378a..7e58a194 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs +++ b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs @@ -2,12 +2,12 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading.Tasks; using Dapper; +using Microsoft.Extensions.Caching.Memory; using MySqlConnector; using osu.Framework.IO.Network; using osu.Game.Beatmaps; @@ -29,14 +29,29 @@ public class BeatmapStore { private static readonly bool use_realtime_difficulty_calculation = Environment.GetEnvironmentVariable("REALTIME_DIFFICULTY") != "0"; private static readonly string beatmap_download_path = Environment.GetEnvironmentVariable("BEATMAP_DOWNLOAD_PATH") ?? "https://osu.ppy.sh/osu/{0}"; + private static readonly uint memory_cache_size_limit = uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SIZE_LIMIT") ?? "1000"); + private static readonly uint memory_cache_sliding_expiration_seconds = uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SLIDING_EXPIRATION_SECONDS") ?? "3600"); + + private static TimeSpan memoryCacheSlidingExpiration => TimeSpan.FromSeconds(memory_cache_sliding_expiration_seconds); + + private readonly MemoryCache attributeMemoryCache; + private readonly MemoryCache beatmapMemoryCache; - private readonly ConcurrentDictionary beatmapCache = new ConcurrentDictionary(); - private readonly ConcurrentDictionary attributeCache = new ConcurrentDictionary(); private readonly IReadOnlyDictionary blacklist; private BeatmapStore(IEnumerable> blacklist) { this.blacklist = new Dictionary(blacklist); + + attributeMemoryCache = new MemoryCache(new MemoryCacheOptions + { + SizeLimit = memory_cache_size_limit, + }); + + beatmapMemoryCache = new MemoryCache(new MemoryCacheOptions + { + SizeLimit = memory_cache_size_limit, + }); } /// @@ -84,21 +99,24 @@ public static async Task CreateAsync(MySqlConnection connection, M return calculator.Calculate(mods); } - BeatmapDifficultyAttribute[]? rawDifficultyAttributes; - LegacyMods legacyModValue = getLegacyModsForAttributeLookup(beatmap, ruleset, mods); DifficultyAttributeKey key = new DifficultyAttributeKey((uint)beatmap.OnlineID, (uint)ruleset.RulesetInfo.OnlineID, (uint)legacyModValue); - if (!attributeCache.TryGetValue(key, out rawDifficultyAttributes)) - { - rawDifficultyAttributes = attributeCache[key] = (await connection.QueryAsync( - "SELECT * FROM osu_beatmap_difficulty_attribs WHERE `beatmap_id` = @BeatmapId AND `mode` = @RulesetId AND `mods` = @ModValue", new - { - key.BeatmapId, - key.RulesetId, - key.ModValue - }, transaction: transaction)).ToArray(); - } + BeatmapDifficultyAttribute[]? rawDifficultyAttributes = await attributeMemoryCache.GetOrCreateAsync( + key, + async cacheEntry => + { + cacheEntry.SetSlidingExpiration(memoryCacheSlidingExpiration); + cacheEntry.SetSize(1); + + return (await connection.QueryAsync( + "SELECT * FROM osu_beatmap_difficulty_attribs WHERE `beatmap_id` = @BeatmapId AND `mode` = @RulesetId AND `mods` = @ModValue", new + { + key.BeatmapId, + key.RulesetId, + key.ModValue + }, transaction: transaction)).ToArray(); + }); if (rawDifficultyAttributes == null || rawDifficultyAttributes.Length == 0) return null; @@ -134,15 +152,20 @@ private static LegacyMods getLegacyModsForAttributeLookup(APIBeatmap beatmap, Ru /// The . /// An existing transaction. /// The retrieved beatmap, or null if not existing. - public async Task GetBeatmapAsync(uint beatmapId, MySqlConnection connection, MySqlTransaction? transaction = null) + public Task GetBeatmapAsync(uint beatmapId, MySqlConnection connection, MySqlTransaction? transaction = null) { - if (beatmapCache.TryGetValue(beatmapId, out var beatmap)) - return beatmap; + return beatmapMemoryCache.GetOrCreateAsync( + beatmapId, + cacheEntry => + { + cacheEntry.SetSlidingExpiration(memoryCacheSlidingExpiration); + cacheEntry.SetSize(1); - return beatmapCache[beatmapId] = await connection.QuerySingleOrDefaultAsync("SELECT * FROM osu_beatmaps WHERE `beatmap_id` = @BeatmapId", new - { - BeatmapId = beatmapId - }, transaction: transaction); + return connection.QuerySingleOrDefaultAsync("SELECT * FROM osu_beatmaps WHERE `beatmap_id` = @BeatmapId", new + { + BeatmapId = beatmapId + }, transaction: transaction); + }); } /// diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/osu.Server.Queues.ScoreStatisticsProcessor.csproj b/osu.Server.Queues.ScoreStatisticsProcessor/osu.Server.Queues.ScoreStatisticsProcessor.csproj index 61cfec57..4815bb71 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/osu.Server.Queues.ScoreStatisticsProcessor.csproj +++ b/osu.Server.Queues.ScoreStatisticsProcessor/osu.Server.Queues.ScoreStatisticsProcessor.csproj @@ -13,6 +13,7 @@ + From 8fa48ee86de3b90f3f5b6b471a5f5d7f9ed877ff Mon Sep 17 00:00:00 2001 From: James Wilson Date: Wed, 17 Apr 2024 20:13:08 +0100 Subject: [PATCH 02/10] refactor `memory_cache_sliding_expiration` --- .../Stores/BeatmapStore.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs index 7e58a194..8107c576 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs +++ b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs @@ -30,9 +30,7 @@ public class BeatmapStore private static readonly bool use_realtime_difficulty_calculation = Environment.GetEnvironmentVariable("REALTIME_DIFFICULTY") != "0"; private static readonly string beatmap_download_path = Environment.GetEnvironmentVariable("BEATMAP_DOWNLOAD_PATH") ?? "https://osu.ppy.sh/osu/{0}"; private static readonly uint memory_cache_size_limit = uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SIZE_LIMIT") ?? "1000"); - private static readonly uint memory_cache_sliding_expiration_seconds = uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SLIDING_EXPIRATION_SECONDS") ?? "3600"); - - private static TimeSpan memoryCacheSlidingExpiration => TimeSpan.FromSeconds(memory_cache_sliding_expiration_seconds); + private static readonly TimeSpan memory_cache_sliding_expiration = TimeSpan.FromSeconds(uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SLIDING_EXPIRATION_SECONDS") ?? "3600")); private readonly MemoryCache attributeMemoryCache; private readonly MemoryCache beatmapMemoryCache; @@ -106,7 +104,7 @@ public static async Task CreateAsync(MySqlConnection connection, M key, async cacheEntry => { - cacheEntry.SetSlidingExpiration(memoryCacheSlidingExpiration); + cacheEntry.SetSlidingExpiration(memory_cache_sliding_expiration); cacheEntry.SetSize(1); return (await connection.QueryAsync( @@ -158,7 +156,7 @@ private static LegacyMods getLegacyModsForAttributeLookup(APIBeatmap beatmap, Ru beatmapId, cacheEntry => { - cacheEntry.SetSlidingExpiration(memoryCacheSlidingExpiration); + cacheEntry.SetSlidingExpiration(memory_cache_sliding_expiration); cacheEntry.SetSize(1); return connection.QuerySingleOrDefaultAsync("SELECT * FROM osu_beatmaps WHERE `beatmap_id` = @BeatmapId", new From 28081cc2ff18a47f10095f9878ba6578e1af5426 Mon Sep 17 00:00:00 2001 From: tsunyoku Date: Wed, 24 Apr 2024 10:12:05 +0100 Subject: [PATCH 03/10] remove store recycling for `BeatmapStore` --- .../Processors/ScorePerformanceProcessor.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/Processors/ScorePerformanceProcessor.cs b/osu.Server.Queues.ScoreStatisticsProcessor/Processors/ScorePerformanceProcessor.cs index 2aa3ea73..197c1ddc 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/Processors/ScorePerformanceProcessor.cs +++ b/osu.Server.Queues.ScoreStatisticsProcessor/Processors/ScorePerformanceProcessor.cs @@ -114,11 +114,11 @@ public async Task ProcessScoreAsync(SoloScoreInfo score, MySqlConnection connect long currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); - if (buildStore == null || beatmapStore == null || currentTimestamp - lastStoreRefresh > 60_000) + beatmapStore ??= await BeatmapStore.CreateAsync(connection, transaction); + + if (buildStore == null || currentTimestamp - lastStoreRefresh > 60_000) { buildStore = await BuildStore.CreateAsync(connection, transaction); - beatmapStore = await BeatmapStore.CreateAsync(connection, transaction); - lastStoreRefresh = currentTimestamp; } From d168720a4e20c2ad89ccf500a42b85557f590c13 Mon Sep 17 00:00:00 2001 From: tsunyoku Date: Wed, 24 Apr 2024 12:16:51 +0100 Subject: [PATCH 04/10] use MB for memory cache size --- .../Stores/BeatmapStore.cs | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs index 8107c576..03f5532d 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs +++ b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs @@ -29,9 +29,19 @@ public class BeatmapStore { private static readonly bool use_realtime_difficulty_calculation = Environment.GetEnvironmentVariable("REALTIME_DIFFICULTY") != "0"; private static readonly string beatmap_download_path = Environment.GetEnvironmentVariable("BEATMAP_DOWNLOAD_PATH") ?? "https://osu.ppy.sh/osu/{0}"; - private static readonly uint memory_cache_size_limit = uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SIZE_LIMIT") ?? "1000"); + private static readonly uint memory_cache_size_limit = uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SIZE_LIMIT") ?? "100"); private static readonly TimeSpan memory_cache_sliding_expiration = TimeSpan.FromSeconds(uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SLIDING_EXPIRATION_SECONDS") ?? "3600")); + /// + /// The size of a in megabytes. Used for tracking memory usage. + /// + private const int beatmap_difficulty_attribute_size = 24 / 1024 / 1024; + + /// + /// The size of a in megabytes. Used for tracking memory usage. + /// + private const int beatmap_size = 72 / 1024 / 1024; + private readonly MemoryCache attributeMemoryCache; private readonly MemoryCache beatmapMemoryCache; @@ -105,15 +115,18 @@ public static async Task CreateAsync(MySqlConnection connection, M async cacheEntry => { cacheEntry.SetSlidingExpiration(memory_cache_sliding_expiration); - cacheEntry.SetSize(1); - return (await connection.QueryAsync( + BeatmapDifficultyAttribute[]? attributes = (await connection.QueryAsync( "SELECT * FROM osu_beatmap_difficulty_attribs WHERE `beatmap_id` = @BeatmapId AND `mode` = @RulesetId AND `mods` = @ModValue", new { key.BeatmapId, key.RulesetId, key.ModValue }, transaction: transaction)).ToArray(); + + cacheEntry.SetSize(beatmap_difficulty_attribute_size * attributes.Length); + + return attributes; }); if (rawDifficultyAttributes == null || rawDifficultyAttributes.Length == 0) @@ -157,7 +170,7 @@ private static LegacyMods getLegacyModsForAttributeLookup(APIBeatmap beatmap, Ru cacheEntry => { cacheEntry.SetSlidingExpiration(memory_cache_sliding_expiration); - cacheEntry.SetSize(1); + cacheEntry.SetSize(beatmap_size); return connection.QuerySingleOrDefaultAsync("SELECT * FROM osu_beatmaps WHERE `beatmap_id` = @BeatmapId", new { From c50297f19e29ce63ebcbe0c39762c01623aeee33 Mon Sep 17 00:00:00 2001 From: tsunyoku Date: Wed, 24 Apr 2024 12:21:35 +0100 Subject: [PATCH 05/10] fix nullability --- .../Stores/BeatmapStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs index 03f5532d..428afe50 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs +++ b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs @@ -116,7 +116,7 @@ public static async Task CreateAsync(MySqlConnection connection, M { cacheEntry.SetSlidingExpiration(memory_cache_sliding_expiration); - BeatmapDifficultyAttribute[]? attributes = (await connection.QueryAsync( + BeatmapDifficultyAttribute[] attributes = (await connection.QueryAsync( "SELECT * FROM osu_beatmap_difficulty_attribs WHERE `beatmap_id` = @BeatmapId AND `mode` = @RulesetId AND `mods` = @ModValue", new { key.BeatmapId, From a111eca3929fc68c4a21b552eb92c0d99cfe98c4 Mon Sep 17 00:00:00 2001 From: tsunyoku Date: Wed, 24 Apr 2024 12:33:24 +0100 Subject: [PATCH 06/10] change size to bytes --- .../Stores/BeatmapStore.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs index 428afe50..1ef04976 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs +++ b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs @@ -29,18 +29,18 @@ public class BeatmapStore { private static readonly bool use_realtime_difficulty_calculation = Environment.GetEnvironmentVariable("REALTIME_DIFFICULTY") != "0"; private static readonly string beatmap_download_path = Environment.GetEnvironmentVariable("BEATMAP_DOWNLOAD_PATH") ?? "https://osu.ppy.sh/osu/{0}"; - private static readonly uint memory_cache_size_limit = uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SIZE_LIMIT") ?? "100"); + private static readonly uint memory_cache_size_limit = uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SIZE_LIMIT") ?? "1000000"); private static readonly TimeSpan memory_cache_sliding_expiration = TimeSpan.FromSeconds(uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SLIDING_EXPIRATION_SECONDS") ?? "3600")); /// - /// The size of a in megabytes. Used for tracking memory usage. + /// The size of a in bytes. Used for tracking memory usage. /// - private const int beatmap_difficulty_attribute_size = 24 / 1024 / 1024; + private const int beatmap_difficulty_attribute_size = 24; /// - /// The size of a in megabytes. Used for tracking memory usage. + /// The size of a in bytes. Used for tracking memory usage. /// - private const int beatmap_size = 72 / 1024 / 1024; + private const int beatmap_size = 72; private readonly MemoryCache attributeMemoryCache; private readonly MemoryCache beatmapMemoryCache; From 2f603b7c22f6b53de53b4718394b96e8c562c053 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2024 18:51:46 +0900 Subject: [PATCH 07/10] Cache full `DifficultyAttributes` as per upstream changes --- .../Stores/BeatmapStore.cs | 49 ++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs index 61700683..ba6b0510 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs +++ b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs @@ -37,6 +37,11 @@ public class BeatmapStore /// private const int beatmap_difficulty_attribute_size = 24; + /// + /// The rough size of base class in bytes. + /// + private const int difficulty_attribute_size = 24; + /// /// The size of a in bytes. Used for tracking memory usage. /// @@ -125,32 +130,40 @@ public async Task GetDifficultyAttributesAsync(Beatmap bea DifficultyAttributeKey key = new DifficultyAttributeKey(beatmap.beatmap_id, (uint)ruleset.RulesetInfo.OnlineID, (uint)legacyModValue); - BeatmapDifficultyAttribute[]? rawDifficultyAttributes = await attributeMemoryCache.GetOrCreateAsync( + return (await attributeMemoryCache.GetOrCreateAsync( key, async cacheEntry => { - cacheEntry.SetSlidingExpiration(memory_cache_sliding_expiration); - - BeatmapDifficultyAttribute[] attributes = (await connection.QueryAsync( - "SELECT * FROM osu_beatmap_difficulty_attribs WHERE `beatmap_id` = @BeatmapId AND `mode` = @RulesetId AND `mods` = @ModValue", new - { - key.BeatmapId, - key.RulesetId, - key.ModValue - }, transaction: transaction)).ToArray(); + try + { + DifficultyAttributes attribs = LegacyRulesetHelper.CreateDifficultyAttributes(ruleset.RulesetInfo.OnlineID); - cacheEntry.SetSize(beatmap_difficulty_attribute_size * attributes.Length); + BeatmapDifficultyAttribute[] dbAttribs = (await connection.QueryAsync( + "SELECT * FROM osu_beatmap_difficulty_attribs WHERE `beatmap_id` = @BeatmapId AND `mode` = @RulesetId AND `mods` = @ModValue", new + { + key.BeatmapId, + key.RulesetId, + key.ModValue + }, transaction: transaction)).ToArray(); - return attributes; - }); + attribs.FromDatabaseAttributes(dbAttribs.ToDictionary(a => (int)a.attrib_id, a => (double)a.value), beatmap); - if (rawDifficultyAttributes == null || rawDifficultyAttributes.Length == 0) - return null; + cacheEntry.SetSlidingExpiration(memory_cache_sliding_expiration); - DifficultyAttributes difficultyAttributes = LegacyRulesetHelper.CreateDifficultyAttributes(ruleset.RulesetInfo.OnlineID); - difficultyAttributes.FromDatabaseAttributes(rawDifficultyAttributes.ToDictionary(a => (int)a.attrib_id, a => (double)a.value), beatmap); + // approximated + cacheEntry.SetSize(difficulty_attribute_size + beatmap_difficulty_attribute_size * dbAttribs.Length); - return difficultyAttributes; + return attribs; + } + catch (Exception ex) + { + throw new DifficultyAttributesMissingException(key, ex); + } + finally + { + Interlocked.Increment(ref attribCacheMiss); + } + }))!; } /// From 23115fcba2d7f70a666cda9f7d898cbccb916367 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2024 19:01:18 +0900 Subject: [PATCH 08/10] Increase default cache size --- .../Stores/BeatmapStore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs index ba6b0510..03b9a9fe 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs +++ b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs @@ -29,7 +29,7 @@ public class BeatmapStore { private static readonly bool use_realtime_difficulty_calculation = Environment.GetEnvironmentVariable("REALTIME_DIFFICULTY") != "0"; private static readonly string beatmap_download_path = Environment.GetEnvironmentVariable("BEATMAP_DOWNLOAD_PATH") ?? "https://osu.ppy.sh/osu/{0}"; - private static readonly uint memory_cache_size_limit = uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SIZE_LIMIT") ?? "1000000"); + private static readonly uint memory_cache_size_limit = uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SIZE_LIMIT") ?? "128000000"); private static readonly TimeSpan memory_cache_sliding_expiration = TimeSpan.FromSeconds(uint.Parse(Environment.GetEnvironmentVariable("MEMORY_CACHE_SLIDING_EXPIRATION_SECONDS") ?? "3600")); /// From 18667560c486dbe7453861e135c64bc007659714 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2024 19:04:39 +0900 Subject: [PATCH 09/10] Fix weird code change --- .../Processors/ScorePerformanceProcessor.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/Processors/ScorePerformanceProcessor.cs b/osu.Server.Queues.ScoreStatisticsProcessor/Processors/ScorePerformanceProcessor.cs index cbc7b7f3..d7131046 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/Processors/ScorePerformanceProcessor.cs +++ b/osu.Server.Queues.ScoreStatisticsProcessor/Processors/ScorePerformanceProcessor.cs @@ -124,12 +124,11 @@ public async Task ProcessScoreAsync(SoloScore score, MySqlConnection conne long currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); - BeatmapStore ??= await BeatmapStore.CreateAsync(connection, transaction); - - if (buildStore == null || (refresh_stores_periodically && currentTimestamp - lastStoreRefresh > 60_000)) + if (buildStore == null || BeatmapStore == null || (refresh_stores_periodically && currentTimestamp - lastStoreRefresh > 60_000)) { buildStore = await BuildStore.CreateAsync(connection, transaction); BeatmapStore = await BeatmapStore.CreateAsync(connection, transaction); + lastStoreRefresh = currentTimestamp; } From 223a2cda822d62f90aa3ac7d945d9ad1ad19a654 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 31 Oct 2024 19:06:58 +0900 Subject: [PATCH 10/10] Code formatting pass --- .../Stores/BeatmapStore.cs | 90 +++++++++---------- 1 file changed, 40 insertions(+), 50 deletions(-) diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs index 03b9a9fe..6a4a758d 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs +++ b/osu.Server.Queues.ScoreStatisticsProcessor/Stores/BeatmapStore.cs @@ -126,44 +126,37 @@ public async Task GetDifficultyAttributesAsync(Beatmap bea return calculator.Calculate(mods); } - LegacyMods legacyModValue = getLegacyModsForAttributeLookup(beatmap, ruleset, mods); + DifficultyAttributeKey key = new DifficultyAttributeKey(beatmap.beatmap_id, (uint)ruleset.RulesetInfo.OnlineID, (uint)getLegacyModsForAttributeLookup(beatmap, ruleset, mods)); - DifficultyAttributeKey key = new DifficultyAttributeKey(beatmap.beatmap_id, (uint)ruleset.RulesetInfo.OnlineID, (uint)legacyModValue); + return (await attributeMemoryCache.GetOrCreateAsync(key, async cacheEntry => + { + try + { + BeatmapDifficultyAttribute[] dbAttributes = (await connection.QueryAsync( + "SELECT * FROM osu_beatmap_difficulty_attribs WHERE `beatmap_id` = @BeatmapId AND `mode` = @RulesetId AND `mods` = @ModValue", new + { + key.BeatmapId, + key.RulesetId, + key.ModValue + }, transaction: transaction)).ToArray(); + + // approximated + cacheEntry.SetSize(difficulty_attribute_size + beatmap_difficulty_attribute_size * dbAttributes.Length); + cacheEntry.SetSlidingExpiration(memory_cache_sliding_expiration); - return (await attributeMemoryCache.GetOrCreateAsync( - key, - async cacheEntry => + DifficultyAttributes attributes = LegacyRulesetHelper.CreateDifficultyAttributes(ruleset.RulesetInfo.OnlineID); + attributes.FromDatabaseAttributes(dbAttributes.ToDictionary(a => (int)a.attrib_id, a => (double)a.value), beatmap); + return attributes; + } + catch (Exception ex) { - try - { - DifficultyAttributes attribs = LegacyRulesetHelper.CreateDifficultyAttributes(ruleset.RulesetInfo.OnlineID); - - BeatmapDifficultyAttribute[] dbAttribs = (await connection.QueryAsync( - "SELECT * FROM osu_beatmap_difficulty_attribs WHERE `beatmap_id` = @BeatmapId AND `mode` = @RulesetId AND `mods` = @ModValue", new - { - key.BeatmapId, - key.RulesetId, - key.ModValue - }, transaction: transaction)).ToArray(); - - attribs.FromDatabaseAttributes(dbAttribs.ToDictionary(a => (int)a.attrib_id, a => (double)a.value), beatmap); - - cacheEntry.SetSlidingExpiration(memory_cache_sliding_expiration); - - // approximated - cacheEntry.SetSize(difficulty_attribute_size + beatmap_difficulty_attribute_size * dbAttribs.Length); - - return attribs; - } - catch (Exception ex) - { - throw new DifficultyAttributesMissingException(key, ex); - } - finally - { - Interlocked.Increment(ref attribCacheMiss); - } - }))!; + throw new DifficultyAttributesMissingException(key, ex); + } + finally + { + Interlocked.Increment(ref attribCacheMiss); + } + }))!; } /// @@ -191,23 +184,20 @@ private static LegacyMods getLegacyModsForAttributeLookup(Beatmap beatmap, Rules /// The . /// An existing transaction. /// The retrieved beatmap, or null if not existing. - public Task GetBeatmapAsync(uint beatmapId, MySqlConnection connection, MySqlTransaction? transaction = null) - { - return beatmapMemoryCache.GetOrCreateAsync( - beatmapId, - cacheEntry => - { - Interlocked.Increment(ref beatmapCacheMiss); + public Task GetBeatmapAsync(uint beatmapId, MySqlConnection connection, MySqlTransaction? transaction = null) => beatmapMemoryCache.GetOrCreateAsync( + beatmapId, + cacheEntry => + { + Interlocked.Increment(ref beatmapCacheMiss); - cacheEntry.SetSlidingExpiration(memory_cache_sliding_expiration); - cacheEntry.SetSize(beatmap_size); + cacheEntry.SetSlidingExpiration(memory_cache_sliding_expiration); + cacheEntry.SetSize(beatmap_size); - return connection.QuerySingleOrDefaultAsync("SELECT * FROM osu_beatmaps WHERE `beatmap_id` = @BeatmapId", new - { - BeatmapId = beatmapId - }, transaction: transaction); - }); - } + return connection.QuerySingleOrDefaultAsync("SELECT * FROM osu_beatmaps WHERE `beatmap_id` = @BeatmapId", new + { + BeatmapId = beatmapId + }, transaction: transaction); + }); /// /// Whether performance points may be awarded for the given beatmap and ruleset combination.