2010-08-24 19 views
5

Próbuję zaimportować dużą ilość danych do podstawowego magazynu danych w telefonie iPhone. Używam podkładu SQLite dla głównej składnicy danych. Wydaje się, że trwa to znacznie dłużej, niż oczekiwałbym. Zmniejszyłem procedury tak, aby zasadniczo było to po prostu pobranie obiektu (aby sprawdzić, czy już istnieje), a następnie utworzenie nowego obiektu, jeśli tak nie jest (nigdy nie robią, ponieważ importuję dane). Pobieranie nie jest jednak czasochłonne. To tworzenie obiektów. Zasadniczo, jest kod naruszającym przepisy:Jak poprawić wydajność wkładki obiektu Core Data na telefonie iPhone?

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

Zauważyłem, że na symulatorze, jest dość szybki na starcie z około 100 obiektów stworzył drugi. Spowalnia jednak spowolnienie i do czasu, gdy powstaje pięć tysięcy obiektów, to prawie 2 sekundy dla 100 obiektów i do czasu utworzenia 10 tysięcy obiektów, to 4 sekundy na 100 obiektów. Cała grupa 21000 obiektów zajmuje więcej niż 10 minut. Jest tak ze wszystkimi rzeczywistymi użytymi kodami (to tylko pobranie i tworzenie obiektu). Na urządzeniu jest znacznie wolniej (o 4 razy więcej).

Nie rozumiem, dlaczego dane podstawowe zaczynają się szybko, ale potem zaczynają zwalniać. Próbowałem zarówno z indeksem i bez indeksów na moich danych. Próbowałem już stworzyć własną pulę autorelease, którą okresowo drenuję w swojej pętli. Próbowałem oszczędzać po każdym stworzeniu obiektu. Próbowałem czekać do końca, aby zapisać. Ale bez względu na to, co robię, występ nadal wydaje się nieszczęśliwy. Czy to jest tak powolne dodawanie nowego obiektu do podstawowego magazynu danych z kilkoma tysiącami obiektów? Jakieś sugestie?

+0

Muszę skomentować, że faktycznie uważam, że te pobrania zabierają znaczną ilość czasu. Przypuszczam, że ma to sens, ponieważ gdy sklep staje się większy, jest więcej obiektów do przeszukiwania. – Mike

+0

Na marginesie, obsada w powyższym przykładowym kodzie jest niepotrzebna. '-insertNewObjectForEntity ...' zwraca 'identyfikator', a zatem nie ma i nie powinien być rzutowany. –

+1

Tworzenie ogromnej bazy danych w ten sposób może być niewiarygodnie powolne, jeśli czeka się do końca, aby zapisać. Generalnie oszczędzam po kilku tysiącach nowych obiektów, nie eksperymentowałem, aby znaleźć optymalną częstotliwość. –

Odpowiedz

0

Spróbuj użyć instrumentów. Nie zapisujesz po wstawieniu każdego obiektu? W rzeczywistości bardzo użyteczny może być więcej kodu i schematu związanego z wkładaniem.

2

Może to być dość szybkie, ale zależy to od tego, co robisz. Jak inni sugerują, powinieneś patrzeć na Instrumenty i znajdować rzeczywisty hotspot. Zamieszczenie rzeczywistego kodu importu pomoże zidentyfikować problem.

+0

Dla mnie, ja * używam * Instrumentów i mówi mi, że _sharedIMPL_addObjectToSet_core zajmuje 99% czas - z kolei obserwator wartości klucza NSObject pobiera 50%, a _PF_ManagedObject_DidChangeValueForKeywithSetMutation przyjmuje pozostałe 50%.Łączę relację wiele do wielu pomiędzy tysiącami jednostek "Zdania" - są to tłumaczenia między sobą. Nawet po wypróbowaniu pewnych optymalizacji, powolnym winowajcą jest naprawdę związek "wstawka", który prawdopodobnie pojawia się za kulisami w CoreData. Po prostu mam wrażenie, że byłoby to co najmniej 50% szybsze, gdyby użyć bezpośredniego sqlite :-P – Jonny

+0

SQLite jest szybsze niż dane podstawowe. Core Data nie będzie najszybsza, jest najbardziej konserwowalna. Jeśli chodzi o Instruments, ukryj biblioteki systemowe, spłaszcz rekursję i odwróć drzewo wywołań. Zobacz, co jest na górze, to jest ** TWÓJ ** kod. To właśnie musisz naprawić. Kiedy znajdziesz metodę, która jest twoja, kliknij ją dwukrotnie, a Instruments pokaże ci, co jest wolne * wewnątrz * tej metody. –

+0

Dokładnie to zrobiłem. Przeszedłem do mej funkcji, która zawierała pętlę kilkuset tysięcy relacji wiele do wielu dla tylko jednej istoty - tak, te zdania są tłumaczeniami nawzajem. Pomyślałem, że pośrednie NSDictionaries, których użyłem dla danych źródłowych, były wolne z indeksowaniem i zrobiłem tam pewną optymalizację, ale Instruments wyraźnie pokazał, że problem nie dotyczy NSDictionary, tylko wewnętrznych operacji wstawiania. Który naprawdę używa sqlite na końcu. Ostatnim razem, gdy wypróbowałem Core Data, również miałem problem ze zbyt małą wydajnością i działałem tylko z Sqlite. – Jonny

0

Mam również ten problem. Importuję 100 000 prostych obiektów ze zdalnego magazynu danych i śledzę notatki Apple dotyczące importowania partiami. Pierwsze kilka partii (po 2000 obiektów każda) rozpoczyna się w rozsądny sposób, a następnie oszczędza powolne przechodzenie.

Podzieliłem dane dalej na partie o wartości 50 i wciąż było wolne. Instrumenty pokazują, że oszczędzanie za każdym razem trwa dłużej. Nie wiem, dlaczego, tworzę nowy kontekst dla każdej partii, a menedżer cofania jest ustawiony na zero.

Niestety, nie mam nic przydatnego do dodania do tej rozmowy ... jeszcze. Zaktualizuje się później.

+0

Kolejnym krokiem będzie wyizolowanie problemu w projekcie testowym, aby inni mogli go zobaczyć, a potencjalnie, jeśli jest on nierozwiązywalny, wysłać go do firmy Apple jako radar. Podobnie jak w przypadku OP, jedna linia kodu lub opis nie pozwalają nikomu na pomoc. –

Powiązane problemy