gle*_*enc 8 performance scalability core-data nsmanagedobjectcontext ios
当我尝试从服务器发送的数据构建初始数据库时,我遇到了基于CoreData的iOS应用程序的问题.基本上,服务器发送1MB的对象块(每个块约3,000个),iOS客户端对它们进行反序列化并将它们写入磁盘.
我所看到的是,对于前8个块(44个)中的一切都进展顺利,然后性能急剧下降,每个块开始花费的时间越来越长,如下图所示.[NSManagedObjectContext save]正如您在仪器分析数据中看到的那样,几乎所有时间都消耗掉了,但似乎应用程序由于某种原因不再以100%的CPU运行,就像它正在等待磁盘I/O或其他东西一样.

关于我是如何做到的一些重要事实:
每个块在其自身的处理NSManagedObjectContext与它自己的NSAutoreleasePool,所以没有对象积聚在组块的处理之间的非冲洗上下文.
NSUndoManager任何情境都没有设定.
没有mergeChangesFromContextDidSaveNotification:进行(即块上下文没有将其更改推送到"主"上下文)
我在iOS 4.3上使用基于SQLite的数据存储.
正在编写的记录确实有索引.
整个同步作业在单个GCD后台线程上处理(即dispatch_queue_create()和dispatch_async()).
我不知道为什么性能突然下降,或者可以采取什么措施来解决它.我已经四处寻找并阅读以下内容,但我还没有突然出现:
任何想法或指针使这个应用程序在数据库中扩展到100,000个记录将非常感激.
这个Instruments图表显示了与上面相同的模拟(在iPad2上),但包括磁盘活动统计数据,你可以清楚地看到所有"不在100%CPU运行"的时间似乎都被写入磁盘.

我还在iOS模拟器上运行了相同的同步尝试.除了包含随时间略微增长的对象ID的字典外,每个块的总内存使用量或多或少是恒定的(但这些不是CoreData对象或任何会影响保存的东西,它们只是NSNumbers).与总堆相比,此dict是少量内存,因此问题不会耗尽内存.
这个测试的有趣之处在于CoreData Save仪器报告连续保存花费的时间大致相同,这显然与第一组结果中的CPU分析信息冲突.似乎CoreData认为将更改推送到数据库需要花费相同的时间,但数据库本身(即SQLite)突然需要更长的时间才能将这些更改实际流式传输到磁盘.
我知道这是一个老问题,所以这可能不再适用于你,但它可能对其他人而言.
我已经看到了通过iCloud播种核心数据数据库的性能问题,并发现如果你在数据模型上有反向关系,那么你可能会非常严重地损害性能.iCloud事务日志记录的实现方式,实际上似乎是一个不可避免的问题.发送给iCloud的每个事务(在developer.icloud.com上查看它们 - 它们只是压缩了plist)记录了受更改影响的每个关系.与在Core Data中修改关系的一端并且负责反向结束时不同,核心数据事务日志结束时记录两个端点的更改,而不是将其解决.
因此,如果你有1对多的关系,并且你创建了另一条记录,最终会挂掉'很多'的结尾 - 那么'1'端的记录也会更新,以反映现在新的额外记录挂掉它.如果你的架构意味着你有一个"类型"对象,许多"数据"对象都会挂起,那么每次添加一个新的数据对象时,类型一个也会为它编写一个事务 - 但是这里是踢球者,因为iCloud核心数据事务记录了已编辑实体的整体状态,而不仅仅是更改,已经记录的每个关系也会添加到日志中,而不仅仅是指示新下级记录的那个.随着实体之间关系数量的增加,随着写入数据量的增加,这可能会迅速失控 - 最终需要更长时间才能保存批次.
我之前在 Apple开发论坛上回答了一个类似这样的问题,这可能很有用,因为我似乎无法简洁地描述这个问题.
如果这种情况影响你,那么提高播种性能的最简单方法是关闭反向关系,但这并不总是一种选择.
有关您的实施的更多信息将会有所帮助。例如,您是在主线程上运行它还是实现后台线程?不过,我以前见过这种行为。使用 Core Data 执行大量批处理操作时,如果内存管理不当,速度可能会变慢。你检查过内存使用情况吗?你检查过有没有漏水吗?另一件要尝试的事情是确保您在需要时正确使用 NSAutoreleasePool。通过定期排空池,这可能有助于提高性能。
| 归档时间: |
|
| 查看次数: |
2116 次 |
| 最近记录: |