swift – 核心数据多NSManagedObjectContext性能难题

swift – 核心数据多NSManagedObjectContext性能难题,第1张

概述我有一个iOS核心数据性能问题,我没有能够弄清楚。我的应用程序有一个相对简单的UICollectionViewController,具有创建NSFetchedResultsController的功能,大致如下: func loadCollection(collectionID: String) { let fetchRequest = NSFetchRequest(entityName: 我有一个iOS核心数据性能问题,我没有能够弄清楚。我的应用程序有一个相对简单的UICollectionVIEwController,具有创建NSFetchedResultsController的功能,大致如下:
func loadCollection(collectionID: String) {    let fetchRequest = NSFetchRequest(entityname: "Story")    fetchRequest.predicate = nspredicate(format: "collectionID == %@ AND wasDeleted == FALSE",collectionID)    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "yearMonthDay",ascending: true),NSSortDescriptor(key: "startDate",ascending: true)]    fetchRequest.fetchBatchSize = 100    self.fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest,managedobjectContext: mainObjectContext!,sectionnameKeyPath: "yearMonth",cachename: collectionID)    var error: NSError?    self.fetchedResultsController.performFetch(&error)    ....}

我的核心数据堆栈看起来像以下两个管理对象上下文,以改善新的和编辑的“故事”对象的对象保存的UI响应时间。这是我在marcus Zarra的核心数据书和blog post等地方看到的基本模式。

// Variation "A" with two managed object contexts.lazy var mainObjectContext: NSManagedobjectContext? = {    if let coordinator = self.persistentStoreCoordinator {        self.rootContext = NSManagedobjectContext(concurrencyType: .PrivateQueueConcurrencyType)        self.rootContext?.persistentStoreCoordinator = coordinator        let managedobjectContext = NSManagedobjectContext(concurrencyType: .MainQueueConcurrencyType)        managedobjectContext.parentContext = self.rootContext        return managedobjectContext      } else {        return nil    }}()

问题是当我有两个如上所述的上下文时,上面的最初的fetchedResultsController.performFetch()比以前只有一个(.MainQueueConcurrencyType)上下文的时间要长约10倍。

例如,使用两个上下文和大约1,700个对象执行上面的抓取在iPad Air上占用5秒以上,但只有一个上下文不到0.4秒。

// Variation "B" with one managed object context.    lazy var mainObjectContext: NSManagedobjectContext? = {        if let coordinator = self.persistentStoreCoordinator {            let managedobjectContext = NSManagedobjectContext(concurrencyType: .MainQueueConcurrencyType)            managedobjectContext.persistentStoreCoordinator = coordinator            return managedobjectContext          } else {            return nil        }    }()

我打开了核心数据记录(-com.apple.CoreData.sqlDeBUG 1),从日志记录我可以看到,当我有两个对象上下文时,1,700个对象的所有属性正在从sql数据库加载以进行初始提取。但是,如果我只有一个上下文,则不会从数据库初始加载属性。

Log from variation "A" with two object contexts:    2015-08-18 13:31:49.761 Myapp[27646:4374573] CoreData: sql: SELECT 0,t0.Z_PK,t0.Z_OPT,t0.ZautocreateD,t0.ZBLOCKS,t0.ZCHANGetoKEN,t0.ZColLECTIONID,t0.ZCREATIONDATE,t0.ZEDITDATE,t0.ZenDDATE,t0.ZFulLTEXT,t0.ZGLOBALID,t0.ZLOCATION,t0.ZLOCATIONTEXT,t0.ZSTARTDATE,t0.ZTags,t0.ZthumbnailIMAGE,t0.ZTIMEZONE,t0.ZTitle,t0.ZWASDELETED,t0.ZYEARMONTH,t0.ZYEARMONTHDAY FROM ZSTORY t0 WHERE ( t0.ZColLECTIONID = ? AND  t0.ZWASDELETED = ?) ORDER BY t0.ZYEARMONTHDAY,t0.ZSTARTDATE    2015-08-18 13:31:52.093 Myapp[27646:4374573] CoreData: annotation: sql connection fetch time: 2.3314s    2015-08-18 13:31:55.011 Myapp[27646:4374573] CoreData: annotation: total fetch execution time: 5.2502s for 1743 rows.    2015-08-18 13:31:55.016 Myapp[27646:4374573] CoreData: sql: SELECT t0.ZYEARMONTH,COUNT (disTINCT  t0.Z_PK) FROM ZSTORY t0 WHERE ( t0.ZColLECTIONID = ? AND  t0.ZWASDELETED = ?) GROUP BY  t0.ZYEARMONTH ORDER BY t0.ZYEARMONTH    2015-08-18 13:31:55.276 Myapp[27646:4374573] CoreData: annotation: sql connection fetch time: 0.2590s    2015-08-18 13:31:55.276 Myapp[27646:4374573] CoreData: annotation: total fetch execution time: 0.2600s for 371 rows.    Log from variation "B" with one object context:    2015-08-18 13:25:19.448 Myapp[27635:4362501] CoreData: sql: SELECT 0,t0.Z_PK FROM ZSTORY t0 WHERE ( t0.ZColLECTIONID = ? AND  t0.ZWASDELETED = ?) ORDER BY t0.ZYEARMONTHDAY,t0.ZSTARTDATE    2015-08-18 13:25:19.789 Myapp[27635:4362501] CoreData: annotation: sql connection fetch time: 0.3405s    2015-08-18 13:25:19.789 Myapp[27635:4362501] CoreData: annotation: total fetch execution time: 0.3410s for 1743 rows.    2015-08-18 13:25:19.790 Myapp[27635:4362501] CoreData: sql: SELECT t0.ZYEARMONTH,COUNT (disTINCT  t0.Z_PK) FROM ZSTORY t0 WHERE ( t0.ZColLECTIONID = ? AND  t0.ZWASDELETED = ?) GROUP BY  t0.ZYEARMONTH ORDER BY t0.ZYEARMONTH    2015-08-18 13:25:19.825 Myapp[27635:4362501] CoreData: annotation: sql connection fetch time: 0.0339s    2015-08-18 13:25:19.825 Myapp[27635:4362501] CoreData: annotation: total fetch execution time: 0.0349s for 371 rows.

所以基于这些结果,我修改了loadCollection函数来添加

fetchRequest.includesPropertyValues = false

现在有两个对象上下文,我得到以下,初始加载时间在0.4秒以下 – 优秀!:

2015-08-18 13:53:43.345 Myapp[27692:4414951] CoreData: sql: SELECT 0,t0.ZSTARTDATE    2015-08-18 13:53:43.683 Myapp[27692:4414951] CoreData: annotation: sql connection fetch time: 0.3378s    2015-08-18 13:53:43.684 Myapp[27692:4414951] CoreData: annotation: total fetch execution time: 0.3383s for 1743 rows.    2015-08-18 13:53:43.688 Myapp[27692:4414951] CoreData: sql: SELECT t0.ZYEARMONTH,COUNT (disTINCT  t0.Z_PK) FROM ZSTORY t0 WHERE ( t0.ZColLECTIONID = ? AND  t0.ZWASDELETED = ?) GROUP BY  t0.ZYEARMONTH ORDER BY t0.ZYEARMONTH    2015-08-18 13:53:43.722 Myapp[27692:4414951] CoreData: annotation: sql connection fetch time: 0.0329s    2015-08-18 13:53:43.722 Myapp[27692:4414951] CoreData: annotation: total fetch execution time: 0.0339s for 371 rows.

但是,现在为NSFetchedResultsController获取的每个对象都是一个错误,导致一行SQL查询,这显着减慢了集合视图滚动:

2015-08-18 13:53:44.078 Myapp[27692:4414951] CoreData: sql: SELECT 0,t0.ZYEARMONTHDAY FROM ZSTORY t0 WHERE  t0.Z_PK = ? 2015-08-18 13:53:44.081 Myapp[27692:4414951] CoreData: annotation: sql connection fetch time: 0.0011s2015-08-18 13:53:44.081 Myapp[27692:4414951] CoreData: annotation: total fetch execution time: 0.0029s for 1 rows.2015-08-18 13:53:44.082 Myapp[27692:4414951] CoreData: annotation: fault fulfilled from database for : 0xd00000001ad8000c <x-coredata://967F5940-D73C-48E2-A26D-E60FF87BA9F7/Story/p1718>

而不是使用100个左右的批次,并且includePropertyValues默认为true:

2015-08-18 14:47:44.221 Myapp[27792:4515252] CoreData: sql: SELECT 0,t0.ZYEARMONTHDAY FROM ZSTORY t0 WHERE  t0.Z_PK IN (SELECT * FROM _Z_intarray0)  ORDER BY t0.ZYEARMONTHDAY,t0.ZSTARTDATE liMIT 1002015-08-18 14:47:44.468 Myapp[27792:4515252] CoreData: annotation: sql connection fetch time: 0.0959s2015-08-18 14:47:44.469 Myapp[27792:4515252] CoreData: annotation: total fetch execution time: 0.2566s for 100 rows.2015-08-18 14:47:44.550 Myapp[27792:4515252] CoreData: sql: SELECT 0,t0.ZYEARMONTHDAY FROM ZSTORY t0 WHERE  t0.Z_PK IN  (?,?,?)  ORDER BY t0.ZYEARMONTHDAY,t0.ZSTARTDATE liMIT 1002015-08-18 14:47:44.614 Myapp[27792:4515252] CoreData: annotation: sql connection fetch time: 0.0067s2015-08-18 14:47:44.614 Myapp[27792:4515252] CoreData: annotation: total fetch execution time: 0.0635s for 44 rows.

任何关于更好的方法的想法或建议将是最受赞赏的。

这是NSFetchedResultsController和批量大小的已知问题。您不能在不丢失batchSize功能的情况下使用Parent-Child上下文。详见 answer。

换句话说,如果您需要使用NSFetchedResultsController并且需要最佳性能,则必须将其附加到主线程上下文,并且该上下文必须附加到持久存储协调器。

总结

以上是内存溢出为你收集整理的swift – 核心数据多NSManagedObjectContext性能难题全部内容,希望文章能够帮你解决swift – 核心数据多NSManagedObjectContext性能难题所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1052878.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存