From 740fdfa883bf6b5b7f59a985d007d3dd33fbd77c Mon Sep 17 00:00:00 2001 From: Christopher Snowhill Date: Thu, 10 Feb 2022 22:37:37 -0800 Subject: [PATCH] Attempt to wrangle memory usage from artwork Now cache around NSData objects of individual pieces of album art, unique by their byte contents. And the artwork image cacher will also use the art ID keys from the database as the cache keys for NSImages, so they'll not only be only read once per unique image, but also tracks can have unique artwork per track, if the files so feature it. Signed-off-by: Christopher Snowhill --- Playlist/PlaylistEntry.h | 2 ++ Playlist/PlaylistEntry.m | 6 ++++-- Utils/SQLiteStore.h | 1 + Utils/SQLiteStore.m | 12 +++++++++++- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Playlist/PlaylistEntry.h b/Playlist/PlaylistEntry.h index 6e90c31b6..e24884b06 100644 --- a/Playlist/PlaylistEntry.h +++ b/Playlist/PlaylistEntry.h @@ -13,6 +13,7 @@ NSInteger shuffleIndex; NSInteger dbIndex; NSInteger entryId; + NSInteger artId; BOOL current; BOOL removed; @@ -106,6 +107,7 @@ @property NSInteger shuffleIndex; @property NSInteger dbIndex; @property NSInteger entryId; +@property NSInteger artId; @property(readonly) NSString *status; @property(readonly) NSString *statusMessage; diff --git a/Playlist/PlaylistEntry.m b/Playlist/PlaylistEntry.m index 68ebc33fe..2728dfd8b 100644 --- a/Playlist/PlaylistEntry.m +++ b/Playlist/PlaylistEntry.m @@ -15,6 +15,7 @@ @synthesize shuffleIndex; @synthesize dbIndex; @synthesize entryId; +@synthesize artId; @synthesize current; @synthesize removed; @@ -373,7 +374,7 @@ - (NSImage *)albumArt { if(!albumArtInternal || ![albumArtInternal length]) return nil; - NSString *imageCacheTag = [NSString stringWithFormat:@"%@-%@-%@-%@", album, artist, genre, year]; + NSString *imageCacheTag = [NSString stringWithFormat:@"%ld", artId]; NSImage *image = [NSImage imageNamed:imageCacheTag]; if(image == nil) { @@ -457,6 +458,7 @@ pe->shuffleIndex = shuffleIndex; pe->dbIndex = dbIndex; pe->entryId = entryId; + pe->artId = artId; pe->current = current; pe->removed = removed; @@ -482,7 +484,7 @@ pe->cuesheet = [cuesheet copyWithZone:zone]; - pe->albumArtInternal = [albumArtInternal copyWithZone:zone]; + pe->albumArtInternal = albumArtInternal; // Only allocated item not duplicated pe->replayGainAlbumGain = replayGainAlbumGain; pe->replayGainAlbumPeak = replayGainAlbumPeak; diff --git a/Utils/SQLiteStore.h b/Utils/SQLiteStore.h index 411b38fcb..5b4cf0424 100644 --- a/Utils/SQLiteStore.h +++ b/Utils/SQLiteStore.h @@ -19,6 +19,7 @@ sqlite3_stmt *stmt[39]; @private NSMutableArray *databaseMirror; + NSMutableDictionary *artTable; } @property(nonatomic, readwrite) NSString *databasePath; diff --git a/Utils/SQLiteStore.m b/Utils/SQLiteStore.m index 6dec23726..1d4bd485f 100644 --- a/Utils/SQLiteStore.m +++ b/Utils/SQLiteStore.m @@ -879,6 +879,8 @@ static SQLiteStore *g_sharedStore = NULL; } } + [artTable setValue:art forKey:[[NSNumber numberWithInteger:ret] stringValue]]; + return ret; } @@ -886,6 +888,9 @@ static SQLiteStore *g_sharedStore = NULL; if(artId < 0) return [NSData data]; + NSData *ret = [artTable valueForKey:[[NSNumber numberWithInteger:artId] stringValue]]; + if(ret) return ret; + sqlite3_stmt *st = stmt[stmt_select_art_value]; if(sqlite3_reset(st) || @@ -900,7 +905,7 @@ static SQLiteStore *g_sharedStore = NULL; return [NSData data]; } - NSData *ret = [NSData data]; + ret = [NSData data]; if(rc == SQLITE_ROW) { const void *blob = sqlite3_column_blob(st, select_art_value_out_value); @@ -912,6 +917,8 @@ static SQLiteStore *g_sharedStore = NULL; sqlite3_reset(st); + [artTable setValue:ret forKey:[[NSNumber numberWithInteger:artId] stringValue]]; + return ret; } @@ -945,6 +952,8 @@ static SQLiteStore *g_sharedStore = NULL; } if(refcount <= 1) { + [artTable removeObjectForKey:[[NSNumber numberWithInteger:artId] stringValue]]; + st = stmt[stmt_remove_art]; if(sqlite3_reset(st) || @@ -1361,6 +1370,7 @@ static SQLiteStore *g_sharedStore = NULL; [entry setReplayGainTrackGain:replaygaintrackgain]; [entry setReplayGainTrackPeak:replaygaintrackpeak]; + [entry setArtId:artId]; [entry setAlbumArtInternal:[self getArt:artId]]; [entry setMetadataLoaded:!!metadataloaded];