tensor核心性能_提高核心数据性能的6个技巧

tensor核心性能

Writing Core Data code with performance in mind helps to prepare your app for the future. Your database might be small in the beginning, but it can easily grow, resulting in slow queries and worse user experience.

考虑性能而编写核心数据代码有助于为将来的应用做好准备。 您的数据库起初可能很小,但是可以轻松增长,从而导致查询速度慢和用户体验差。

Since I started writing the Collect by WeTransfer app in 2017, I’ve been writing a lot of Core Data-related code, touching it almost every day. With millions of users adding lots of content, performing Core Data-related code has become an important skill in our team.

自从我于2017年开始编写Collect by WeTransfer应用程序以来,我一直在编写许多与Core Data相关的代码,几乎每天都涉及到它。 随着数百万用户添加大量内容,执行与Core Data相关的代码已成为我们团队中的一项重要技能。

Over the years, we’ve developed lots of insights and I’m happy to share six tips you should know.

多年来,我们已经积累了许多见解,很高兴分享您应该知道的六个技巧。

1.利用后台管理对象上下文 (1. Make Use of a Background Managed Object Context)

One thing we didn’t do from the start is to make use of a background managed object context. We only used the view context to perform any Core Data-related tasks: inserting new content, deleting content, fetching content, etc.

我们从一开始就没有做过的一件事就是利用后台托管对象上下文。 我们仅使用视图上下文执行任何与Core Data相关的任务:插入新内容,删除内容,获取内容等。

In the beginning, our app was relatively small. Only making use of the view context wasn’t really an issue and didn’t result in any visible performance penalties related to Core Data. Obviously, once our app started to grow, we realized that the view context was associated with the main queue. Slow queries blocked our UI and our app became less responsive.

最初,我们的应用程序相对较小。 仅使用视图上下文并不是真正的问题,也不会导致与Core Data相关的任何可见的性能损失。 显然,一旦我们的应用开始增长,我们就意识到视图上下文与主队列相关联。 缓慢的查询阻止了我们的用户界面,并且我们的应用程序响应速度变慢。

In general, a best practice is to perform data processing on a background queue, as it can be CPU-intensive. Examples like importing JSON into Core Data could otherwise block the view context and result in unresponsiveness in the user interface.

通常,最佳实践是在后台队列上执行数据处理,因为它可能会占用大量CPU。 诸如将JSON导入Core Data中的示例可能会阻塞视图上下文并导致用户界面无响应。

The solution is to make use of a background managed object context. The latest APIs make it easy to create a new context from your persistent container:

解决方案是利用后台管理对象上下文。 最新的API使从持久性容器创建新上下文变得容易:

let backgroundContext = persistentContainer.newBackgroundContext()

I recommend this method over the NSManagedObjectContext(concurrenyType:) initializer, as it will automatically be associated with the NSPersistentStoreCoordinator and will be set to consume NSManagedObjectContextDidSave broadcasts too. This keeps your background context in sync with the view context.

我建议在NSManagedObjectContext(concurrenyType:)初始化程序上使用此方法,因为该方法将自动与NSPersistentStoreCoordinator关联,并且还将设置为使用NSManagedObjectContextDidSave广播。 这样可以使您的背景上下文与视图上下文保持同步。

You can save this background context on a custom persistent container subclass. This way, you can reuse your background context and only have to manage two contexts. This keeps your Core Data structure simple to understand and prevents having multiple out-of-sync contexts.

您可以将此背景上下文保存在自定义的持久性容器子类上。 这样,您可以重用后台上下文,而只需要管理两个上下文。 这使您的核心数据结构易于理解,并避免了多个不同步的上下文。

If you only have to use the background context in a few places, you can also decide to use the performBackgroundTask(_:) method that creates a background context in place:

如果只需要在几个地方使用背景上下文,则还可以决定使用performBackgroundTask(_:)方法在适当的位置创建背景上下文:

persistentContainer.performBackgroundTask { (backgroundContext) in
// .. Core Data Code
}

However, this method creates a new NSManagedObjectContext each time it is invoked. You might want to consider using the shared background context if you're dispatching more often to a background context.

但是,此方法每次调用时都会创建一个新的NSManagedObjectContext 。 如果您要更频繁地分派到后台上下文,则可能要考虑使用共享的后台上下文。

不要在队列之间传递NSManagedObject实例 (Don’t pass NSManagedObject instances between queues)

Writing multi-threaded Core Data code is a lot more complex than using a single view context. The reason for this is that you can’t simply pass an NSManagedObject instantiated from a view context to a background context. Doing so would result in a crash and potential data corruption.

编写多线程Core Data代码比使用单个视图上下文要复杂得多。 这样做的原因是,您不能简单地将实例化的NSManagedObject从视图上下文传递到背景上下文。 这样做会导致崩溃和潜在的数据损坏。

When it’s necessary to move a managed object from one queue to another, you can make use of NSManagedObjectID, which is thread-safe:

当需要将托管对象从一个队列移到另一个队列时,可以使用NSManagedObjectID ,它是线程安全的:

2.仅在需要时保存托管对象上下文 (2. Only Save a Managed Object Context if Needed)

Saving a managed object context commits all current changes to the context’s parent store. As you can imagine, this is not a cheap operation and it should only be used if needed to ensure performance in Core Data.

保存受管对象上下文会将所有当前更改提交到上下文的父存储。 可以想像,这不是一个便宜的操作,只有在需要时才能使用它,以确保Core Data的性能。

First of all, it’s important to check if there’s even anything to save. If there are no changes to commit, there’s also no reason to perform a save. By creating a saveIfNeeded method, you allow yourself to easily build in a check for this:

首先,重要的是检查是否还有要保存的东西。 如果没有要提交的更改,也没有理由执行保存。 通过创建saveIfNeeded方法,您可以轻松地为此建立检查:

仔细考虑何时保存更改 (Carefully consider when to save your changes)

Apart from using saveIfNeeded instead of save(), you also need to consider whether a save makes sense. Although a context could have changed, directly committing these changes is not always necessary.

除了使用saveIfNeeded而不是save() ,您还需要考虑保存是否有意义。 尽管上下文可能已更改,但不一定总是直接提交这些更改。

For example, if you’re importing multiple items into your database, you might only want to save after you’ve imported all items on your background context. A save is often followed by UI updates, and multiple saves after one another could easily result in unnecessary reloads. Besides that, take into account that saved changes in a background context are merged into the view context, blocking the main queue shortly as well. Therefore, be conscious!

例如,如果要将多个项目导入数据库,则可能只想在将所有项目导入背景上下文后进行保存。 一次保存后通常会进行UI更新,而且一次又一次的多次保存很容易导致不必要的重新加载。 除此之外,还要考虑到在后台上下文中保存的更改已合并到视图上下文中,并且很快也会阻塞主队列。 因此,要有意识!

3.只获取您所需要的 (3. Only Fetch What You Need)

Fetching data is an expensive task and needs to be as performant as possible to make your app prepared for large datasets. The following code is a common mistake:

提取数据是一项昂贵的任务,需要尽可能地提高性能,以使您的应用程序为大型数据集做好准备。 以下代码是一个常见错误:

This code will load all inserted objects into memory while it’s being filtered for content with a name.

这段代码将过滤所有带有名称的内容时将所有插入的对象加载到内存中。

It’s much more performant to use predicates to only fetch the objects that are needed. The filter above can be written as followed with a NSPredicate:

使用谓词仅获取所需对象的性能更高。 上面的过滤器可以写成NSPredicate

This has two advantages:

这有两个优点:

  • Only the needed objects are loaded into memory.

    仅将所需的对象加载到内存中。
  • You don’t need to iterate over all objects.

    您不需要遍历所有对象。

Predicates are very flexible and should allow you to fetch the desired dataset in most cases while maintaining performance in Core Data.

谓词非常灵活,在大多数情况下都应允许您获取所需的数据集,同时保持Core Data的性能。

4.利用提取限制 (4. Make Use of Fetch Limits)

Following up on the previous example, it’s important to set fetch limits when you’re only going to display a part of the dataset.

继续前面的示例,当您仅要显示数据集的一部分时,设置获取限制很重要。

For example, say that you only need the first three names of all the content items. In this case, it would be unnecessary to load all the content items that have a name into memory. We could prevent this by setting a fetch limit:

例如,假设您只需要所有内容项的前三个名称。 在这种情况下,没有必要将所有具有名称的内容项加载到内存中。 我们可以通过设置提取限制来防止这种情况:

This code will only return the first three content items with a name.

此代码将仅返回前三个内容名称。

5.使用NSBatchDeleteRequest一次删除许多对象 (5. Delete Many Objects at Once Using an NSBatchDeleteRequest)

Instead of iterating over a dataset deleting each object one by one, it’s often more performant to use a NSBatchDeleteRequest that runs faster as it operates at the SQL level in the persistent store itself.

与其遍历一个删除每个对象的数据集, NSBatchDeleteRequest使用一个NSBatchDeleteRequest来提高性能,因为NSBatchDeleteRequest在持久性存储本身中以SQL级别运行,因此运行速度更快。

You can learn more about batch delete requests in a previous article I wrote.

您可以在我撰写的上一篇文章中了解有关批量删除请求的更多信息。

6.知道如何调试核心数据代码 (6. Know How to Debug Core Data Code)

As with all code you write, it’s important to know how to optimize and debug it once it’s not performing as expected. There are many ways of debugging that are best explained in my dedicated blog post.

与您编写的所有代码一样,重要的是要知道一旦性能未达到预期就如何对其进行优化和调试。 在我的专用博客文章中 ,有许多关于调试的方法的最佳解释。

结论 (Conclusion)

Writing performant Core Data code from the beginning helps you to prepare your app for future large datasets. Although your app might be performing at the beginning, it can easily slow down once your database and model grow. By making use of a background context, smart fetch requests, and batch delete requests, you’re already making your Core Data code more performant.

从一开始就编写高性能的Core Data代码可帮助您为将来的大型数据集准备应用程序。 尽管您的应用程序可能在一开始就表现良好,但是一旦数据库和模型增长,它很容易放慢速度。 通过使用后台上下文,智能获取请求和批量删除请求,您已经在使核心数据代码更具性能。

Thanks for reading!

谢谢阅读!

翻译自: https://medium.com/better-programming/6-tips-for-better-core-data-performance-d7ff8fc07f36

tensor核心性能

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值