1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-27 02:01:18 +08:00

Improve efficiency of tag population (#37228)

- No longer holds realm write transaction open while performing sqlite
lookups.
- No longer attempts a write transaction when it will be a noop.

I'll admit that this is maybe working around the actual realm write part
being slow, but as I can't profile the issue locally, the sluggishness
may actually be in sqlite for those users affected (since it's only been
reported for tag population and not difficulty calculation?).

Regardless, this should fix the issue this iteration.

I also adjusted the user messaging to let them know why tag population
is happening, since we've had some questions as to why it's running in
the first place (it only happens once a month, so that's
understandable).

- [x] Depends on https://github.com/ppy/osu/pull/37227.
- Closes https://github.com/ppy/osu/issues/34699.
- Closes https://github.com/ppy/osu/issues/37210.

Note that https://github.com/ppy/osu/pull/36128 also exists and has
valid improvements which can be addressed separately. This is intended
to be something we can act on immediately.

---------

Co-authored-by: Bartłomiej Dach <dach.bartlomiej@gmail.com>
This commit is contained in:
Dean Herbert
2026-04-08 00:02:32 +09:00
committed by GitHub
Unverified
parent c570db6c40
commit 84cce2f0d1
@@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@@ -655,7 +656,8 @@ namespace osu.Game.Database
if (metadataSourceFetchDate <= lastPopulation)
{
Logger.Log($@"Skipping user tag population because the local metadata source hasn't been updated since the last time user tags were checked ({lastPopulation.Value:d})");
Logger.Log(
$@"Skipping user tag population because the local metadata source hasn't been updated since the last time user tags were checked ({lastPopulation.Value.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture)})");
return;
}
@@ -675,9 +677,11 @@ namespace osu.Game.Database
Logger.Log($@"Found {beatmapIds.Count} beatmaps with missing user tags.");
var notification = showProgressNotification(beatmapIds.Count, @"Populating missing user tags", @"beatmaps have had their tags updated.");
var notification = showProgressNotification(beatmapIds.Count, @"Populating missing user tags",
@"beatmaps have had their tags updated. This runs once a month to allow searching user tags.");
int processedCount = 0;
int updatedCount = 0;
int failedCount = 0;
foreach (var id in beatmapIds)
@@ -691,33 +695,37 @@ namespace osu.Game.Database
try
{
// Can't use async overload because we're not on the update thread.
// ReSharper disable once MethodHasAsyncOverload
realmAccess.Write(r =>
var beatmap = realmAccess.Run(r => r.Find<BeatmapInfo>(id)?.Detach());
if (beatmap == null) continue;
bool lookupSucceeded = localMetadataSource.TryLookup(beatmap, out var result);
if (lookupSucceeded)
{
BeatmapInfo beatmap = r.Find<BeatmapInfo>(id)!;
Debug.Assert(result != null);
bool lookupSucceeded = localMetadataSource.TryLookup(beatmap, out var result);
HashSet<string> userTags = result.UserTags.ToHashSet();
if (lookupSucceeded)
if (!userTags.SetEquals(beatmap.Metadata.UserTags))
{
Debug.Assert(result != null);
var userTags = result.UserTags.ToHashSet();
if (!userTags.SetEquals(beatmap.Metadata.UserTags))
++updatedCount;
realmAccess.Write(r =>
{
beatmap = r.Find<BeatmapInfo>(id);
if (beatmap == null)
return;
beatmap.Metadata.UserTags.Clear();
beatmap.Metadata.UserTags.AddRange(userTags);
return true;
}
return false;
});
}
}
else
{
Logger.Log(@$"Could not find {beatmap.GetDisplayString()} in local cache while backpopulating missing user tags");
return false;
});
}
++processedCount;
}
@@ -732,7 +740,9 @@ namespace osu.Game.Database
}
}
completeNotification(notification, processedCount, beatmapIds.Count, failedCount);
// Report the updated item count rather than the total processed. Users don't really care about noops here.
completeNotification(notification, updatedCount, updatedCount, failedCount);
config.SetValue(OsuSetting.LastOnlineTagsPopulation, metadataSourceFetchDate);
}
@@ -753,7 +763,11 @@ namespace osu.Game.Database
if (notification == null)
return;
if (processedCount == totalCount)
if (totalCount == 0)
{
notification.CompleteSilently();
}
else if (processedCount == totalCount)
{
notification.CompletionText = $"{processedCount} {notification.CompletionText}";
notification.Progress = 1;