零件中的核心数据优化— 2

本文是“零件中的核心数据优化”的系列文章。 第一部分的链接 在这里

在跳到下一条规则之前,假设您的应用程序必须处理昂贵的对象,并且花大量的CPU资源和时间来初始化此类对象。 图像库就是这样一个示例,其中实际图像由占位符图像Thumbnail代替,它是实际图像的较小表示形式-一种代理。 但是,如果我们要求图像尺寸,则它带有实际图像尺寸。

缩略图具有两个有趣的功能: -a )。 提供较少的内存b)。 具有与实际图像相似的界面(getSize或大小)

使用此缩略图可以减少内存占用,但是当您查询getSize()或大小时,它会返回实际的图像大小。 与该设计相关的软件模式是代理模式 核心数据提取操作按照相同的设计原理进行,并在执行提取时创建故障对象(如缩略图)。

故障对象是托管对象的代理,该代理的内存较少,因为它的所有属性均未初始化

我们如何获得属性?

一旦我们尝试访问任何属性,核心数据就会在此处进行优化- 例如,雇员实体具有薪水属性,然后访问持久性存储以从获取的值中填充属性。 击中持久性存储以获取属性实际值的过程称为触发错误 核心数据的惊人行为与持久性存储中的内置缓存机制中的核心数据相关,持久性存储了实际获取的值。

现在,假设您的业务逻辑基于想要执行以下操作的所有薪水数据:

 对于employeeRecord { 
var total + = aEmployee.salary
} print(“ Average = \(total / count)”

在此,CD将为每个故障对象触发故障,并将进入永久存储,这反过来又增加了往返时间。 在这种情况下,最好进行单次故障或火灾批次故障,而不要对PS(持久存储)进行单独故障。

使用IN的谓词可以改善情况 关键词 并在fetchRequest 上将returnObjectsAsFaults属性设置为false

 let谓词= NSPredicate(格式:“ self IN%@”,employeeRecord) 
fetchRequest。 returnsObjectsAsFaults = false print(“ Average = \(total / count)”

如果以后想要执行更多操作,则可以通过完全实现ManagedObject实体来提高性能。 例如,有关员工搜索的内容,您必须再次获取每个员工的ID。 但是,当您将来不需要操作时,肯定不需要此功能。

这导致下一条规则。

明智地使用它。 如果您希望对象在不久的将来围绕其他一些操作,请执行批处理操作并减少故障开销

核心数据不止于此,以优化行程时间。 在将获取结果缓存到持久性存储中之前,您可以选择不将这些属性值全部带入PS存储缓存中。

设置includePropertyValues为false将仅将objectID缓存到PS缓存。 这将使更少的属性保留在存储高速缓存中,尽管您的对象仍然有问题,但由于持久性存储高速缓存中的属性数据较少,所以我们的内存占用也更少。

  includesPropertyValues = false 

一旦完成对托管对象上下文的操作,我确定您不打算将其保留在上下文中。 您可以重新故障,也可以刷新上下文。

  重新故障refreshObject:mergeChanges: 重置上下文reset 

这导致优化的下一个规则,特别是减少了获取操作期间和获取对象之后的内存开销。

将对象转为故障,偶尔刷新上下文并偶尔使用获取请求缓存PS。

让我们谈谈关系。

考虑公寓和人之间的实体关系。 由于一个公寓可以有多个人,一个人可以住在一个公寓里。 这种关系定义为一对多。

如果您的应用需要显示“人员”及其“地址”。 我们可以做类似的事情:

 让requestPerson = NSFetchRequest (entityName:“ Person”) 
let requestAddress = NSFetchRequest (实体名称:“公寓”)

这是我们获取和显示信息的方式之一。 由于存在两个提取请求,每个实体的取回请求都会增加往返时间。 由于两个获取请求都包含有关联关系的实体,因此Core Data可以优化对有关联关系的实体的获取请求。 上面的提取请求可以进一步优化为:

 让fetchRequest = NSFetchRequest (entityName:“ Person”) 
fetchRequest.relationshipKeyPathsForPrefetching = ["Apartment"]

至少在那些必须处理大量实体的情况下,这可以避免为公寓触发故障并减少往返时间。

在下一篇文章中,我们将探讨Core Data并发模型并建立更多规则。

如果您喜欢这篇文章,可以鼓掌,但不要在这里分享,以便其他人也可以使用。 👏👏👏👏👏