From 88cad2ad1acc158c48de950e0b0adb03d2d84b89 Mon Sep 17 00:00:00 2001 From: Shadowghost Date: Mon, 4 May 2026 01:56:21 +0200 Subject: Speed-up LatestItems for Music --- Emby.Server.Implementations/Dto/DtoService.cs | 50 +++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 6 deletions(-) (limited to 'Emby.Server.Implementations') diff --git a/Emby.Server.Implementations/Dto/DtoService.cs b/Emby.Server.Implementations/Dto/DtoService.cs index cc57d183b6..9f36577410 100644 --- a/Emby.Server.Implementations/Dto/DtoService.cs +++ b/Emby.Server.Implementations/Dto/DtoService.cs @@ -203,6 +203,39 @@ namespace Emby.Server.Implementations.Dto } } + // Batch-fetch MusicArtist lookups across all items to avoid N+1 queries. + IReadOnlyDictionary? artistsBatch = null; + HashSet? artistNames = null; + foreach (var item in accessibleItems) + { + if (item is IHasArtist hasArtist) + { + foreach (var name in hasArtist.Artists) + { + if (!string.IsNullOrWhiteSpace(name)) + { + (artistNames ??= new HashSet(StringComparer.Ordinal)).Add(name); + } + } + } + + if (item is IHasAlbumArtist hasAlbumArtist) + { + foreach (var name in hasAlbumArtist.AlbumArtists) + { + if (!string.IsNullOrWhiteSpace(name)) + { + (artistNames ??= new HashSet(StringComparer.Ordinal)).Add(name); + } + } + } + } + + if (artistNames is { Count: > 0 }) + { + artistsBatch = _libraryManager.GetArtists(artistNames.ToArray()); + } + for (int index = 0; index < accessibleItems.Count; index++) { var item = accessibleItems[index]; @@ -214,7 +247,8 @@ namespace Emby.Server.Implementations.Dto userDataBatch?.GetValueOrDefault(item.Id), allCollectionFolders, childCountBatch, - playedCountBatch); + playedCountBatch, + artistsBatch); if (item is LiveTvChannel tvChannel) { @@ -274,7 +308,8 @@ namespace Emby.Server.Implementations.Dto UserItemData? userData = null, List? allCollectionFolders = null, Dictionary? childCountBatch = null, - Dictionary? playedCountBatch = null) + Dictionary? playedCountBatch = null, + IReadOnlyDictionary? artistsBatch = null) { var dto = new BaseItemDto { @@ -334,7 +369,7 @@ namespace Emby.Server.Implementations.Dto AttachStudios(dto, item); } - AttachBasicFields(dto, item, owner, options); + AttachBasicFields(dto, item, owner, options, artistsBatch); if (options.ContainsField(ItemFields.CanDelete)) { @@ -907,7 +942,8 @@ namespace Emby.Server.Implementations.Dto /// The item. /// The owner. /// The options. - private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem? owner, DtoOptions options) + /// Optional pre-fetched artist lookup shared across a batch of items. + private void AttachBasicFields(BaseItemDto dto, BaseItem item, BaseItem? owner, DtoOptions options, IReadOnlyDictionary? artistsBatch = null) { if (options.ContainsField(ItemFields.DateCreated)) { @@ -1152,7 +1188,8 @@ namespace Emby.Server.Implementations.Dto // Include artists that are not in the database yet, e.g., just added via metadata editor // var foundArtists = artistItems.Items.Select(i => i.Item1.Name).ToList(); - var artistsLookup = _libraryManager.GetArtists([.. hasArtist.Artists.Where(e => !string.IsNullOrWhiteSpace(e))]); + var artistsLookup = artistsBatch + ?? _libraryManager.GetArtists([.. hasArtist.Artists.Where(e => !string.IsNullOrWhiteSpace(e))]); dto.ArtistItems = hasArtist.Artists .Where(name => !string.IsNullOrWhiteSpace(name)) @@ -1186,7 +1223,8 @@ namespace Emby.Server.Implementations.Dto // }) // .ToList(); - var albumArtistsLookup = _libraryManager.GetArtists([.. hasAlbumArtist.AlbumArtists.Where(e => !string.IsNullOrWhiteSpace(e))]); + var albumArtistsLookup = artistsBatch + ?? _libraryManager.GetArtists([.. hasAlbumArtist.AlbumArtists.Where(e => !string.IsNullOrWhiteSpace(e))]); dto.AlbumArtists = hasAlbumArtist.AlbumArtists .Where(name => !string.IsNullOrWhiteSpace(name)) -- cgit v1.2.3