【问题标题】:How to speed up CoreData Migration or another solutions如何加快核心数据迁移或其他解决方案
【发布时间】:2014-02-24 13:45:17
【问题描述】:

我将 Coredata 用于我的 iOS 应用程序。它有大约 20 个表,我的应用程序使用数据库中的可能图像(图像编辑应用程序)。所以数据库数据如此庞大和沉重。

有一天,我在一张表中添加了几列。它只是字符串列。当然我知道如何迁移和实现它,所以我添加了新的 .xcdatamodel 并更改了当前的。当我在我的设备中测试时,我没有收到任何错误和冲突。所以我将它发布到iOS开发者中心,它可以被宣布。终于,很多用户开始更新我的应用了。

但有些用户说“从未完成更新”。 “更新需要 50 分钟。”等等...
更新意味着迁移。我通过用户报告的进度确认了这一点。我不敢相信迁移需要 50 分钟!但也许这是真的。因为当我测试使用 50 张图像并保存到 CoreData 时,我的设备大约需要 1 分钟。我认为我们的客户使用 300 ~ 500 张图像和用户其他数据。如果是 iPhone4 或 iPhone4S,迁移需要很长时间...

所以我想知道如何为这些用户加快 CoreData 迁移。
现在我使用的是自动迁移,否则我可以选择手动迁移。
我发现了一些技巧并告诉工程师,并收集它,我推断手动迁移比自动迁移慢。
我正在寻找其他并行解决方案。它将核心数据导出到 PC。并且 PC 迁移而不是 iPhone。 iPhone 会导入迁移的数据。有谁知道这种方式可行吗?

最后,我放上我的迁移代码。这真的很简单。

@try {
    // init application (Before application:didFinishLaunchingWithOptions:)
LOG(@"start migration");

    NSPersistentStoreCoordinator *migPersistent;

    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:[[self class] sqliteFileInDocumentsUrlString]];
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
                             [NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,nil];
    NSError *error = nil;
    migPersistent = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    if (![migPersistent addPersistentStoreWithType:NSSQLiteStoreType
                                     configuration:nil
                                               URL:storeURL
                                           options:options
                                             error:&error]) {

        NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
        [migPersistent release];
        return NO;
    }

    [migPersistent release];
    LOG(@"finish migration");
}
@catch (NSException *exception) {
    .....
}
@finally {
    // Do Nothing
}

此外,此代码在 MainThread 上运行。
喜欢
ViewDidAppear(LoadingWindow) -> performSelector:withObject:afterDelay -> 迁移。


感谢您观看此问题,对不起,我的英语很糟糕..



编辑于 2014.02.25 21:11

我得到了跟踪文件并上传了以下 URL。
https://www.dropbox.com/sh/dmlf4j4z3vkj3p0/DrDBL_guYy

[测试流程](设备:iPodtouch 5th Gen iOS 7.0.6)
1. 在之前的版本中插入了 195KB(Width:960,Height:1280) x 1000 图片。
2. 安装当前版本并运行迁移。它完成了大约11分钟。

那么为什么用户得到 50 分钟???


编辑于 2014.02.26 8:59

抱歉,以上网址有误。请检查此网址。
https://www.dropbox.com/s/8xaxwyfex7gyjdt/traceFolder.zip


编辑于 2014.02.26 10:43

-[PapeDataManager 迁移] 中发生了什么?如果可以,请添加代码

上面的代码。这个方法得到了 184977x。

[migPersistent addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL
                                           options:options error:&error]


-[PapeDataManager repairImageNamePath] 中发生了什么?

这个方法得到了 160775x。
[self.managedObjectContext save:&error]

self.managedObjectContext 是 NSManagedObjectContext。
保存似乎是一个繁重的过程。因为它是在迁移之后。

现在,我有一些问题。

(1) MainThread 的运行时间总结约为 6 分钟,而 TimeProfiler 上的进程总时间为 11 分钟。为什么会出现这种差异?

(2) 当我在迁移时按下主页按钮时,迁移过程会死机吗?我只是在检查它。但如果你知道这一点。请告诉我。


编辑于 2014.02.26 12:09

关于 (2)。 我已经测试了 50 个图像迁移。
当我按下主页按钮和 30 秒后,后台任务已暂停。

所以像这样的流程
应用程序午餐->加载开始->迁移->(按下HomeButton并将应用程序发送到后台)->迁移完成->后台进程暂停->(推送应用程序图标并将应用程序发送到前台)->保存->加载完成

我不知道为什么应用程序在后台时加载过程不会继续。也许我们的用户对加载时间长感到愤怒的原因就是这个。

【问题讨论】:

  • 我知道这个问题,但没有完整的解决方案。需要这么长时间的原因是整个数据库被读入内存进行迁移。有手动迁移的可能性,您可以在其中微调迁移。请参阅 developer.apple.com/library/mac/documentation/cocoa/conceptual/… 标题为多次传递—处理大型数据集的部分
  • 我建议将代码移到主线程之外,并允许用户在迁移过程中使用应用程序。
  • 也许你应该把图像放在核心数据之外?
  • @Volker 这是不正确的。发生自动/轻量级迁移时,不会将整个数据库加载到内存中。这只发生在大量迁移时。
  • @Volker 如果您使用的是映射模型,那么您正在进行大量迁移。

标签: ios iphone performance core-data database-migration


【解决方案1】:

即使对于自动/轻量级迁移而言,持久存储中的图像似乎花费的时间比正常情况要长得多。

假设您现在已经建立了一个包含 500 张图像的测试用例来跟踪它;下一步是在迁移过程中针对应用程序运行工具,并查看时间花在了哪里。如果时间确实在 Core Data 中(而不是一些 UI 事件正在发生),那么请使用 Instruments 的跟踪编辑您的帖子。

您的应用程序很可能会在迁移后立即尝试对数据执行某些操作,这会消耗时间。没有仪器痕迹很难分辨。

更新(来自跟踪)

-[PapeDataManager migrate] 发生了什么?如果可以,请添加代码

-[PapeDataManager repairImageNamePath] 发生了什么?

-repairImageNamePath 花费的时间最多,如果你能解决这个问题,你会看到性能显着提升。

更新 2

打开SQLite debug 可以让您看到在这段时间内发生了什么。如果由于存储中的 blob 确实是大量的 sql 调用,那么您将需要重构存储,可能进行手动迁移(不是繁重,但从 Core Data 导出并重建文件)来解决此问题。

【讨论】:

  • 感谢您的建议。我应该在仪器中使用哪个库?一些库有.. Time Profiler, Activity Monitor, 等等。
  • 从时间探查器开始。观看有关它的 WWDC 视频。
  • 该跟踪中没有数据。
  • 对不起,我弄错了。请检查新网址。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-14
  • 2013-09-20
  • 2011-11-04
  • 2011-04-07
  • 2011-03-14
相关资源
最近更新 更多