patternMinor
Optimizing a search for list of artists in iTunes library
Viewed 0 times
itunessearchartistsoptimizingforlibrarylist
Problem
I'm trying to get a list of all artists on an iPhone / iPod touch music library. The best way I've found has been to group by artists (the convenience constructor on MPMediaQuery) and to iterate over the collections, being one for each artist. That way I've optimized out having to use an NSSet to ensure uniqueness in the artist list. Still, I need to make each collection into a representative item and get it's artist, which according to Time Profiler takes a very good part of this code snippet.
Wrapping it in some timing blocks, such as below, I've gotten it to run in 0.315 seconds on my iPhone 4 with a library of ~2600 songs and 88 artists, but I feel like that long for only 88 items is way too long.
Does anyone know of a way to make this a bit faster?
NSString *artistKey = [MPMediaItem titlePropertyForGroupingType:MPMediaGroupingArtist];
MPMediaQuery *artistsQuery = [MPMediaQuery artistsQuery];
NSMutableArray *artists = [NSMutableArray arrayWithCapacity:artistsQuery.collections.count];
for (MPMediaItemCollection *album in artistsQuery.collections) {
MPMediaItem *albumItem = [album representativeItem];
[artists addObject:[albumItem valueForProperty:artistKey]];
}Wrapping it in some timing blocks, such as below, I've gotten it to run in 0.315 seconds on my iPhone 4 with a library of ~2600 songs and 88 artists, but I feel like that long for only 88 items is way too long.
NSTimeInterval start = [[NSDate date] timeIntervalSince1970];
// [snip]
NSTimeInterval finish = [[NSDate date] timeIntervalSince1970];
NSLog(@"Execution took %f seconds.", finish - start]);Does anyone know of a way to make this a bit faster?
Solution
Is it actually necessary to add just the artist to the array? We could simply do this:
Now we don't have to iterate through an entire array. And later, when we need to access the artist at a particular array index, we can still get to that value as such:
Also, this SO answer seems to suggest that
At first glance it may seem like this will automatically be slower since you're iterating through every property instead of just accessing the one you need, and in this case, since you only need a single property, this may actually be slower. But if you need multiple properties, this should definitely be faster--enumerations like this (as well as
NSMutableArray *artists = artistsQuery.collections;Now we don't have to iterate through an entire array. And later, when we need to access the artist at a particular array index, we can still get to that value as such:
[[artists[someIndex] representativeItem] valueForProperty:artistKey];Also, this SO answer seems to suggest that
valueForProperty: is just slow in general. Despite only needing the artist, it might be better to enumerate through all the properties:[artistsQuery.collections enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
MPMediaItem *item = (MPMediaItem *)obj;
[item enumerateValuesForProperties:properties usingBlock:^(NSString *property, id value, BOOL *stop) {
if ([property isEqualToString:artistKey]) {
[artists addObject:value];
}
}];
}];At first glance it may seem like this will automatically be slower since you're iterating through every property instead of just accessing the one you need, and in this case, since you only need a single property, this may actually be slower. But if you need multiple properties, this should definitely be faster--enumerations like this (as well as
forin loops) are handled in batches so they run quite fast.Code Snippets
NSMutableArray *artists = artistsQuery.collections;[[artists[someIndex] representativeItem] valueForProperty:artistKey];[artistsQuery.collections enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
MPMediaItem *item = (MPMediaItem *)obj;
[item enumerateValuesForProperties:properties usingBlock:^(NSString *property, id value, BOOL *stop) {
if ([property isEqualToString:artistKey]) {
[artists addObject:value];
}
}];
}];Context
StackExchange Code Review Q#4605, answer score: 3
Revisions (0)
No revisions yet.