Производительность сохранения NSManagedObjectContext резко ухудшается

У меня возникают проблемы с приложением iOS на основе CoreData, когда оно пытается построить исходную базу данных из данных, отправленных с сервера. В основном сервер отправляет блоки объектов размером 1 МБ (около 3000 на блок), а клиент iOS десериализует их и записывает на диск.

Я вижу, что все идет довольно хорошо примерно для первых 8 блоков. (из 44), то производительность резко падает, и каждый фрагмент начинает занимать все больше и больше времени, как на изображении ниже. Практически все время уходит на [NSManagedObjectContext save] , как вы можете видеть в данных профилирования инструментов, но также кажется, что приложение больше не работает на 100% ЦП по какой-то причине, как будто оно ожидание ввода-вывода на диске или что-то в этом роде.

profiling data showing performance degradation

Несколько важных фактов о том, как я это делаю:

  • Каждый фрагмент обрабатывается в собственном NSManagedObjectContext с его собственным NSAutoreleasePool ], поэтому в не очищенном контексте между обработкой фрагментов не происходит наращивания объектов.

  • Нет NSUndoManager , установленного ни в одном из контекстов.

  • Нет mergeChangesFromContextDidSaveNotification: происходит (т.е. контексты фрагментов не передают свои изменения в «главный» контекст)

  • Я использую хранилище данных на основе SQLite в iOS 4.3.

  • В записываемых записях есть индексирует их.

  • Все задание синхронизации обрабатывается в одном фоновом потоке GCD (т.е. dispatch_queue_c reate () и dispatch_async () ).

Я понятия не имею, почему производительность так внезапно падает, и что можно сделать, чтобы это исправить. Я покопался и прочитал следующее, но пока ничего не бросилось мне в глаза:

Мы будем очень признательны за любые идеи или указатели, позволяющие масштабировать это приложение до 100 000 записей в базе данных.

Изменить - дополнительная статистика

] Этот график инструментов показывает ту же симуляцию, что и выше (на iPad2), но включает статистику дисковой активности, и вы можете довольно ясно видеть, что все время «не работает на 100% ЦП», похоже, занято записью на диск.

Disk activity for original test

Я также выполнил ту же попытку синхронизации на симуляторе iOS. Общее использование памяти является более или менее постоянным для каждого фрагмента, за исключением словаря, который содержит идентификаторы объектов, которые со временем немного увеличиваются (но это не объекты CoreData или что-либо, что может повлиять на сохранение, это просто NSNumbers). Это небольшой объем памяти по сравнению с общей кучей, поэтому проблема не в нехватке памяти.

Что интересно в этом тесте, так это то, что инструмент CoreData Save сообщает, что последующие сохранения занимают примерно такой же объем time, что явно противоречит информации профилирования ЦП из первого набора результатов.Похоже, CoreData считает, что столько же времени уходит на отправку изменений в БД, но самой БД (то есть SQLite) внезапно требуется намного больше времени для фактической потоковой передачи этих изменений на диск.

8
задан Community 23 May 2017 в 10:29
поделиться