2010-08-24 2 views
5

Ich versuche, eine große Menge von Daten in einen Kerndatenspeicher auf dem iPhone zu importieren. Ich verwende eine SQLite-Unterstützung für den Core-Datenspeicher. Es scheint länger zu dauern, als ich es erwartet hätte. Ich habe die Routinen so getrimmt, dass es im Grunde nur versucht, ein Objekt zu holen (um zu sehen, ob es bereits existiert) und dann ein neues Objekt zu erstellen, wenn dies nicht der Fall ist (seit dem Datenimport). Das Holen ist jedoch nicht der zeitaufwendige Teil. Es ist die Schaffung der Objekte. Grundsätzlich ist der säumige Code:Wie kann ich die Leistung des Core Data-Objekts auf dem iPhone verbessern?

MobileObject *newObject = (MobileObject *)[NSEntityDescription insertNewObjectForEntityForName:objDesc inManagedObjectContext:managedObjectContext]; 

Ich habe bemerkt, dass auf dem Simulator, es am Anfang ziemlich schnell mit etwa 100 Objekten eine Sekunde erstellt. Es verlangsamt sich jedoch und bis zum Zeitpunkt, an dem fünftausend Objekte erzeugt werden, sind es fast 2 Sekunden für 100 Objekte und zu der Zeit, wenn zehntausend Objekte erzeugt werden, sind es 4 Sekunden pro 100 Objekte. Die gesamte Gruppe von 21000 Objekten benötigt mehr als 10 Minuten. Das ist mit dem ganzen tatsächlich nützlichen Code, der herausgenommen wird (das ist nur ein Fetch und ein Objekt, das erstellt wird). Und es ist viel viel langsamer auf dem tatsächlichen Gerät (um vielleicht 4 mal so viel).

Was ich nicht verstehe ist, warum Core-Daten schnell beginnen, dann aber langsamer werden. Ich habe sowohl mit Index als auch ohne Indizes für meine Daten versucht. Ich habe versucht, meinen eigenen Autorelease-Pool zu erstellen, den ich regelmäßig in meiner Schleife entleere. Ich habe versucht, nach jeder Objekterstellung zu speichern. Ich habe versucht, bis zum Ende zu warten, um zu sparen. Aber egal was ich tue, die Performance scheint immer noch miserabel. Ist es nur langsam, ein neues Objekt zu einem Kerndatenspeicher mit einigen tausend Objekten hinzuzufügen? Irgendwelche Vorschläge?

+0

Ich sollte eigentlich sagen, dass die Fetches diejenigen sind, die eine erhebliche Menge an Zeit benötigen. Ich denke, das macht Sinn, denn wenn der Laden größer wird, gibt es mehr Objekte zu durchsuchen. – Mike

+0

Nebenbei, die Besetzung in Ihrem Beispielcode ist unnötig. '-insertNewObjectForEntity ...' gibt eine 'id' zurück und wird daher nicht umgewandelt. –

+1

Erstellen einer riesigen Datenbank auf diese Weise kann unglaublich langsam sein, wenn Sie bis zum Ende warten, um zu speichern. Generell spare ich nach jeweils einigen tausend neuen Objekten, habe nicht experimentiert, um die optimale Frequenz zu finden. –

Antwort

0

Verwenden Sie Instrumente. Sparen Sie nicht nach dem Einfügen jedes einzelnen Objekts? Tatsächlich kann mehr einfügebezogener Code und Schema sehr nützlich sein.

2

Es kann ziemlich schnell sein, aber es hängt davon ab, was Sie tun. Wie andere vorgeschlagen haben, sollten Sie sich Instrumente ansehen und den eigentlichen Hotspot finden. Auch das Veröffentlichen des tatsächlichen Importcodes würde helfen, das Problem zu identifizieren.

+0

Für mich * bin * mit Instrumenten und es sagt mir _sharedIMPL_addObjectToSet_core nimmt 99% von Die Zeit - wiederum Schlüsselwert Beobachter von NSObject dauert 50%, und _PF_ManagedObject_DidChangeValueForKeywithSetMutation nimmt die anderen 50%.Ich verbinde eine Viele-zu-Viele-Beziehung zwischen Tausenden von "Satz" -Entitäten - das sind Übersetzungen voneinander. Selbst nach einigen Optimierungen ist der langsame Täter wirklich die Beziehung "einfügen", die wahrscheinlich hinter den Kulissen von CoreData abläuft. Ich habe nur das Gefühl, dass dies mindestens 50% schneller wäre, wenn ich direkt sqlite :-P – Jonny

+0

verwenden würde. SQLite ist schneller als Core Data. Core Data wird nicht am schnellsten sein, es ist am besten wartbar. Wie bei Instrumenten, verstecken Sie Systembibliotheken, reduzieren Sie die Rekursion und invertieren Sie den Aufrufbaum. Dann sehen Sie, was oben ist, dass ** IHR ** Code ist. Das müssen Sie beheben. Wenn Sie die Methode gefunden haben, die Ihnen gehört, doppelklicken Sie darauf und Instrumente zeigen Ihnen, was langsam * innerhalb * dieser Methode ist. –

+0

Genau das habe ich getan. Ich habe mich auf meine Funktion konzentriert, die eine Schleife von ein paar hunderttausend von vielen zu vielen Beziehungen für nur eine Entität enthielt - ja, diese Sätze sind Übersetzungen voneinander. Ich dachte, dass die NSDictionaries, die ich für Quelldaten verwendete, mit der Indexierung langsam waren, und ich habe dort einige Optimierungen durchgeführt, aber Instruments zeigte eindeutig, dass das Problem nicht auf NSDictionary, sondern nur auf die INSERT-Operationen zurückzuführen ist. Was am Ende wirklich sqlite benutzt. Das letzte Mal, als ich Core Data ausprobierte, bekam ich auch Probleme mit zu langsamer Performance und ging nur mit Sqlite. – Jonny

0

Ich habe dieses Problem auch. Ich importiere 100.000 einfache Objekte aus einem Remote-Datenspeicher und befolge die Anmerkungen von Apple zum Batch-Import. Die ersten paar Stapel (von jeweils 2000 Objekten) beginnen vernünftig, und dann wird das Speichern langsam zum Crawlen.

Ich habe die Daten weiter in Chargen von 50 partitioniert, und es war immer noch langsam. Instrumente zeigen, dass die Speicherung jedes Mal länger dauert. Ich weiß nicht warum, ich erstelle für jeden Stapel einen neuen Kontext, und der Undo Manager wird auf Null gesetzt.

Leider habe ich nichts nützliches zu dieser Konversation hinzuzufügen ... noch nicht. Wird später aktualisiert.

+0

Der nächste Schritt besteht darin, das Problem in einem Testprojekt zu isolieren, damit andere es sehen können. Wenn es unlösbar ist, senden Sie es möglicherweise als Radar an Apple. Wie beim OP kann eine Zeile Code oder eine Beschreibung Ihnen nicht helfen. –

Verwandte Themen