我们正在研究企业级应用程序,该应用程序将存储数以万计的具有核心数据的对象,并且我们在多个方面存在问题。核心数据被管理对象上下文设计建议
我们的应用程序有几个独立的系统,在需要时对数据进行操作。这些系统包括项目发现,项目加载,同步和UI显示。如果我们正确设计我们的软件,由于不同的系统修改相同的对象,应该几乎没有合并冲突。每个系统都有自己的操作队列,全部在后台执行。我们希望在后台保留所有对象的创建和修改,以最大限度地减少UI性能问题,特别是在初始阶段,可能会从服务器上的数据创建数千个对象。我们在这里尝试了各种设计,遇到了一些问题。这些斜坡上升期间巨大的内存消耗,以及所有上下文和子上下文的错误编排,导致死锁和崩溃。 我们尝试以下设计:
- 一个根
NSPrivateQueueConcurrencyType
其中有一个孩子NSMainQueueConcurrencyType
上下文管理对象上下文。 UI获取的结果控制器使用此子上下文从中获取结果。从NSMainQueueConcurrencyType
子上下文中,我们创建了一个NSPrivateQueueConcurrencyType
子上下文,我们称之为“savingContext”,每个后台操作都创建了该“savingContext”的子上下文,进行了更改,最后做了我们称之为“深度保存”的递归保存到顶部。我们最初选择这种设计时不必处理来自许多不同儿童环境的NSManagedObjectContextDidSaveNotification
通知。我们将每个电话都打包到NSPrivateQueueConcurrencyType
上下文中,并使用performBlockAndWait:
访问对象。在功能上,这个设计进行了。所有更改和插入都保存到持久性存储中,并且UI随更改而更新。这引出了两个问题。其中一个是laggy UI,因为合并后的变化经历了NSMainQueueConcurrencyType
子环境,更重要的是,在升级期间内存使用率非常高。由于无法在上下文上递归调用reset
(因为主UI子上下文也存在)和/或缺乏何时调用refreshObject:mergeChanges:
,所以我们会打击禁用的RAM使用。所以我们走了一条不同的道路。 - 有两个顶级上下文与持久性存储区协调器链接,一个用于保存子上下文的
NSPrivateQueueConcurrencyType
和用于UI显示的NSMainQueueConcurrencyType
。NSMainQueueConcurrencyType
侦听来自主NSPrivateQueueConcurrencyType
上下文的NSManagedObjectContextDidSaveNotification
通知,并将它们合并到主线程中。每个后台操作都创建一个主要NSPrivateQueueConcurrencyType
上下文的子上下文,该子上下文也使用专用队列并发类型,执行它的操作,递归执行“深度保存”,在当前上下文上执行保存操作,深度保存到其上下文的递归调用父母,调用当前上下文重置并再次保存。这样我们可以避免内存问题,因为创建的对象在保存后会很快释放。但是,通过这种设计,我们遇到了很多问题,例如死锁,NSInternalInconsistencyException
例外和提取的结果控制器不更新UI,尽管存在关于NSMainQueueConcurrencyType
上下文的通知。这也会导致UI中的初始加载时间减慢很多。在之前的设计中,抓取的结果控制器返回结果的速度非常快,而这会导致UI停滞几秒,直到视图加载(我们初始化viewDidLoad
中的抓取结果控制器)。
我们已经尝试了很多中间的设计,但它们都围绕着同样的问题,要么非常高的内存使用情况,获取结果控制器不更新UI或死锁和NSInternalInconsistencyException
例外。
我真的很沮丧。我不禁觉得好像我们是这样设计的东西,应该是很简单的公然复杂,它只是我们缺乏了解一些基本的是杀害我们。
那么你们会建议什么?你会根据我们的情况推荐什么样的安排?我们应该如何在不同的线程中管理不同的上下文?释放插入的对象并重置上下文的最佳实践?避免死锁?所有帮助将在此时赞赏。
我也看到了MagicalRecords类别的建议。是否推荐?我们已经投入使用核心数据类型,使用MR迁移有多困难?
我有类似的问题(架构之一):http://stackoverflow.com/questions/15999932/core-data-break-retain-cycle-of-the-parent-context/16008470 - 什么样的架构最后你去了吗?有小费吗? – Zyphrax
我们有一个主要上下文和一个父根上下文。但根上下文仅用于保存,因此我们在每次保存时重置它。我们有很多问题。看起来,这些儿童和家长环境的新特性并没有经过深思熟虑,苹果公司仍然存在很多许多缺陷。 –
我倾向于具有MOC(MainQueue)的子MOC(PrivateQueue)的体系结构,并通过添加'''[self.managedObjectContext refreshObject:self mergeChanges:NO];''''''' '我的一些ManagedObjects中的'-didSave'''。这将打破关系之间的保留周期,并允许所有MOC释放对象。只有NSPrivateQueueConcurrencyType MOCS似乎有一个奇怪的问题,他们不会解除分配的对象,但马上就下保存/回滚。 – Zyphrax