Significantly reduce memory usage all around

Added a string dictionary for deduplication of metadata, and actually
initialize both it and the art dictionary on startup, so they actually
work like they should.

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
CQTexperiment
Christopher Snowhill 2022-02-16 16:57:47 -08:00
parent c242d53200
commit 3de43b55a7
3 changed files with 91 additions and 40 deletions

View File

@ -460,6 +460,7 @@
[self setMetadataLoaded:YES];
}
// Now we duplicate the object to a new handle, but merely reference the same data
- (id)copyWithZone:(NSZone *)zone {
PlaylistEntry *pe = [[[self class] allocWithZone:zone] init];
@ -479,22 +480,22 @@
pe->queuePosition = queuePosition;
pe->error = error;
pe->errorMessage = [errorMessage copyWithZone:zone];
pe->errorMessage = errorMessage;
pe->URL = [URL copyWithZone:zone];
pe->URL = URL;
pe->artist = [artist copyWithZone:zone];
pe->albumartist = [albumartist copyWithZone:zone];
pe->album = [album copyWithZone:zone];
pe->title = [title copyWithZone:zone];
pe->genre = [genre copyWithZone:zone];
pe->year = [year copyWithZone:zone];
pe->track = [track copyWithZone:zone];
pe->disc = [disc copyWithZone:zone];
pe->artist = artist;
pe->albumartist = albumartist;
pe->album = album;
pe->title = title;
pe->genre = genre;
pe->year = year;
pe->track = track;
pe->disc = disc;
pe->cuesheet = [cuesheet copyWithZone:zone];
pe->cuesheet = cuesheet;
pe->albumArtInternal = albumArtInternal; // Only allocated item not duplicated
pe->albumArtInternal = albumArtInternal;
pe->replayGainAlbumGain = replayGainAlbumGain;
pe->replayGainAlbumPeak = replayGainAlbumPeak;
@ -513,11 +514,11 @@
pe->Unsigned = Unsigned;
pe->sampleRate = sampleRate;
pe->codec = [codec copyWithZone:zone];
pe->codec = codec;
pe->endian = [endian copyWithZone:zone];
pe->endian = endian;
pe->encoding = [encoding copyWithZone:zone];
pe->encoding = encoding;
pe->seekable = seekable;

View File

@ -20,6 +20,7 @@
@private
NSMutableArray *databaseMirror;
NSMutableDictionary *artTable;
NSMutableDictionary *stringTable;
}
@property(nonatomic, readwrite) NSString *databasePath;

View File

@ -511,7 +511,7 @@ NSURL *urlForPath(NSString *path) {
}
@interface SQLiteStore (Private)
- (int64_t)addString:(NSString *)string;
- (int64_t)addString:(NSString **)string;
- (NSString *)getString:(int64_t)stringId;
- (void)removeString:(int64_t)stringId;
- (int64_t)addArt:(NSData *)art;
@ -668,6 +668,8 @@ static SQLiteStore *g_sharedStore = NULL;
size_t count = [self playlistGetCount];
databaseMirror = [[NSMutableArray alloc] init];
artTable = [[NSMutableDictionary alloc] init];
stringTable = [[NSMutableDictionary alloc] init];
for(size_t i = 0; i < count; ++i) {
PlaylistEntry *pe = [self playlistGetItem:i];
@ -690,12 +692,12 @@ static SQLiteStore *g_sharedStore = NULL;
}
}
- (int64_t)addString:(NSString *)string {
if(!string || [string length] == 0) {
- (int64_t)addString:(NSString **)string {
if(!*string || [*string length] == 0) {
return -1;
}
const char *str = [string UTF8String];
const char *str = [*string UTF8String];
uint64_t len = strlen(str); // SQLite expects number of bytes, not characters
sqlite3_stmt *st = stmt[stmt_select_string];
@ -732,6 +734,8 @@ static SQLiteStore *g_sharedStore = NULL;
ret = sqlite3_last_insert_rowid(g_database);
refcount = 1;
[stringTable setObject:*string forKey:[[NSNumber numberWithInteger:ret] stringValue]];
} else {
st = stmt[stmt_bump_string];
@ -741,6 +745,8 @@ static SQLiteStore *g_sharedStore = NULL;
sqlite3_reset(st)) {
return -1;
}
*string = [stringTable objectForKey:[[NSNumber numberWithInteger:ret] stringValue]];
}
return ret;
@ -750,6 +756,9 @@ static SQLiteStore *g_sharedStore = NULL;
if(stringId < 0)
return @"";
NSString *ret = [stringTable objectForKey:[[NSNumber numberWithInteger:stringId] stringValue]];
if(ret) return ret;
sqlite3_stmt *st = stmt[stmt_select_string_value];
if(sqlite3_reset(st) ||
@ -764,7 +773,7 @@ static SQLiteStore *g_sharedStore = NULL;
return @"";
}
NSString *ret = @"";
ret = @"";
if(rc == SQLITE_ROW) {
const unsigned char *str = sqlite3_column_text(st, select_string_value_out_value);
@ -817,6 +826,8 @@ static SQLiteStore *g_sharedStore = NULL;
sqlite3_reset(st)) {
return;
}
[stringTable removeObjectForKey:[[NSNumber numberWithInteger:stringId] stringValue]];
} else {
st = stmt[stmt_pop_string];
@ -978,7 +989,7 @@ static SQLiteStore *g_sharedStore = NULL;
NSURL *url = [track URL];
NSString *urlString = [url absoluteString];
int64_t urlId = [self addString:urlString];
int64_t urlId = [self addString:&urlString];
sqlite3_stmt *st = stmt[stmt_select_track];
@ -1005,14 +1016,31 @@ static SQLiteStore *g_sharedStore = NULL;
sqlite3_reset(stmt[stmt_select_string]);
if(rc != SQLITE_ROW) {
int64_t albumId = [self addString:[track album]];
int64_t albumartistId = [self addString:[track albumartist]];
int64_t artistId = [self addString:[track artist]];
int64_t titleId = [self addString:[track rawTitle]];
int64_t genreId = [self addString:[track genre]];
int64_t codecId = [self addString:[track codec]];
int64_t cuesheetId = [self addString:[track cuesheet]];
int64_t encodingId = [self addString:[track encoding]];
NSString *temp;
temp = [track album];
int64_t albumId = [self addString:&temp];
[track setAlbum:temp];
temp = [track albumartist];
int64_t albumartistId = [self addString:&temp];
[track setAlbumartist:temp];
temp = [track artist];
int64_t artistId = [self addString:&temp];
[track setArtist:temp];
temp = [track rawTitle];
int64_t titleId = [self addString:&temp];
[track setTitle:temp];
temp = [track genre];
int64_t genreId = [self addString:&temp];
[track setGenre:temp];
temp = [track codec];
int64_t codecId = [self addString:&temp];
[track setCodec:temp];
temp = [track cuesheet];
int64_t cuesheetId = [self addString:&temp];
[track setCuesheet:temp];
temp = [track encoding];
int64_t encodingId = [self addString:&temp];
[track setEncoding:temp];
int64_t trackNr = [[track track] intValue] | (((uint64_t)[[track disc] intValue]) << 32);
int64_t year = [[track year] intValue];
int64_t unsignedFmt = [track Unsigned];
@ -1021,7 +1049,9 @@ static SQLiteStore *g_sharedStore = NULL;
int64_t bitspersample = [track bitsPerSample];
int64_t channels = [track channels];
int64_t channelConfig = [track channelConfig];
int64_t endianId = [self addString:[track endian]];
temp = [track endian];
int64_t endianId = [self addString:&temp];
[track setEndian:temp];
int64_t floatingpoint = [track floatingPoint];
int64_t totalframes = [track totalFrames];
int64_t metadataloaded = [track metadataLoaded];
@ -1113,7 +1143,7 @@ static SQLiteStore *g_sharedStore = NULL;
NSURL *url = [track URL];
NSString *urlString = [url absoluteString];
int64_t urlId = [self addString:urlString];
int64_t urlId = [self addString:&urlString];
sqlite3_stmt *st = stmt[stmt_select_track];
@ -1201,14 +1231,31 @@ static SQLiteStore *g_sharedStore = NULL;
sqlite3_reset(st);
{
int64_t albumId = [self addString:[track album]];
int64_t albumartistId = [self addString:[track albumartist]];
int64_t artistId = [self addString:[track artist]];
int64_t titleId = [self addString:[track rawTitle]];
int64_t genreId = [self addString:[track genre]];
int64_t codecId = [self addString:[track codec]];
int64_t cuesheetId = [self addString:[track cuesheet]];
int64_t encodingId = [self addString:[track encoding]];
NSString *temp;
temp = [track album];
int64_t albumId = [self addString:&temp];
[track setAlbum:temp];
temp = [track albumartist];
int64_t albumartistId = [self addString:&temp];
[track setAlbumartist:temp];
temp = [track artist];
int64_t artistId = [self addString:&temp];
[track setArtist:temp];
temp = [track rawTitle];
int64_t titleId = [self addString:&temp];
[track setTitle:temp];
temp = [track genre];
int64_t genreId = [self addString:&temp];
[track setGenre:temp];
temp = [track codec];
int64_t codecId = [self addString:&temp];
[track setCodec:temp];
temp = [track cuesheet];
int64_t cuesheetId = [self addString:&temp];
[track setCuesheet:temp];
temp = [track encoding];
int64_t encodingId = [self addString:&temp];
[track setEncoding:temp];
int64_t trackNr = [[track track] intValue] | (((uint64_t)[[track disc] intValue]) << 32);
int64_t year = [[track year] intValue];
int64_t unsignedFmt = [track Unsigned];
@ -1217,7 +1264,9 @@ static SQLiteStore *g_sharedStore = NULL;
int64_t bitspersample = [track bitsPerSample];
int64_t channels = [track channels];
int64_t channelConfig = [track channelConfig];
int64_t endianId = [self addString:[track endian]];
temp = [track endian];
int64_t endianId = [self addString:&temp];
[track setEndian:temp];
int64_t floatingpoint = [track floatingPoint];
int64_t totalframes = [track totalFrames];
int64_t metadataloaded = [track metadataLoaded];