Ich habe eine Reihe von NSFetchedResultsControllers, die einige Tabellenansichten versorgen, und ihre Leistung auf Gerät war miserabel, in der Größenordnung von Sekunden. Da alles auf Haupt-Thread läuft, blockiert es meine App beim Start, was nicht toll ist.
Ich habe nachgeforscht und es stellte sich heraus, dass das Prädikat das Problem ist:
NSPredicate *somePredicate = [NSPredicate predicateWithFormat:@"ANY somethings == %@", something];
[fetchRequest setPredicate:somePredicate];
D.h. die Entität fetch, nennen wir sie "things", hat eine many-to-many Beziehung mit der Entität "something". Dieses Prädikat ist ein Filter, der die Ergebnisse auf die Dinge beschränkt, die eine Beziehung zu einem bestimmten "Etwas" haben.
Als ich das Prädikat zum Testen entfernte, sank die Abrufzeit (der erste performFetch:-Aufruf) (in einigen Extremfällen) von 4 Sekunden auf etwa 100 ms oder weniger, was akzeptabel ist. Das ist akzeptabel. Ich bin jedoch beunruhigt, da dies einen Großteil des Nutzens zunichte macht, den ich mir von Core Data und NSFRC erhofft hatte, die ansonsten ein leistungsfähiges Werkzeug zu sein scheinen.
Meine Frage ist also, wie kann ich diese Leistung optimieren? Verwende ich das Prädikat falsch? Sollte ich das Modell/Schema irgendwie ändern? Und welche anderen Möglichkeiten gibt es, dies zu beheben? Ist diese Art von Leistungseinbußen zu erwarten? (Es handelt sich um Hunderte von <1KB-Objekten.)
MIT DETAILS BEARBEITEN:
Hier ist der Code:
[fetchRequest setFetchLimit:200];
NSLog(@"before fetch");
BOOL success = [frc performFetch:&error];
if (!success) {
NSLog(@"Fetch request error: %@", error);
}
NSLog(@"after fetch");
Aktualisierte Protokolle (früher hatte ich hier einige Anwendungsschwächen, die die Leistung beeinträchtigten. Dies sind die aktualisierten Protokolle, die in meiner aktuellen Umgebung so optimal wie möglich sein sollten):
2010-02-05 12:45:22.138 Special Ppl[429:207] before fetch
2010-02-05 12:45:22.144 Special Ppl[429:207] CoreData: sql: SELECT DISTINCT 0, t0.Z_PK, t0.Z_OPT, <model fields> FROM ZTHING t0 LEFT OUTER JOIN Z_1THINGS t1 ON t0.Z_PK = t1.Z_2THINGS WHERE t1.Z_1SOMETHINGS = ? ORDER BY t0.ZID DESC LIMIT 200
2010-02-05 12:45:22.663 Special Ppl[429:207] CoreData: annotation: sql connection fetch time: 0.5094s
2010-02-05 12:45:22.668 Special Ppl[429:207] CoreData: annotation: total fetch execution time: 0.5240s for 198 rows.
2010-02-05 12:45:22.706 Special Ppl[429:207] after fetch
Wenn ich die gleiche Abfrage ohne Prädikat durchführe (indem ich die beiden Zeilen am Anfang der Frage auskommentiere):
2010-02-05 12:44:10.398 Special Ppl[414:207] before fetch
2010-02-05 12:44:10.405 Special Ppl[414:207] CoreData: sql: SELECT 0, t0.Z_PK, t0.Z_OPT, <model fields> FROM ZTHING t0 ORDER BY t0.ZID DESC LIMIT 200
2010-02-05 12:44:10.426 Special Ppl[414:207] CoreData: annotation: sql connection fetch time: 0.0125s
2010-02-05 12:44:10.431 Special Ppl[414:207] CoreData: annotation: total fetch execution time: 0.0262s for 200 rows.
2010-02-05 12:44:10.457 Special Ppl[414:207] after fetch
20-facher Unterschied in den Zeiten. 500ms ist nicht so groß, und es scheint keine Möglichkeit zu sein, es im Hintergrund-Thread zu tun oder anderweitig zu optimieren, die ich mir vorstellen kann. (Abgesehen von der Umstellung auf einen Binärspeicher, wo dies ein Nicht-Problem wird, also könnte ich das tun. Binärspeicher Leistung ist konsequent ~100ms für die oben genannten 200-Objekt-Predicated-Abfrage).
(Ich habe hier bereits eine andere Frage verschachtelt, die ich jetzt weggezogen ).