【问题标题】:NSManagedObjectContext performBlock and dispatch_group_tNSManagedObjectContext performBlock 和 dispatch_group_t
【发布时间】:2012-12-17 03:02:14
【问题描述】:

问题是我需要修改(更新/创建/删除)从 0 到 10000 个 NSManagedObject 的子类。当然,如果它

+ (void)saveDataInBackgroundWithBlock:(void (^)(NSManagedObjectContext *))saveBlock completion:(void (^)(void))completion {
    NSManagedObjectContext *tempContext = [self newMergableBackgroundThreadContext];
    [tempContext performBlock:^{

        if (saveBlock) {
            saveBlock(tempContext);
        }

        if ([tempContext hasChanges]) {
            [tempContext saveWithCompletion:completion];
        } else {
            dispatch_async(dispatch_get_main_queue(), ^{
                if (completion) {
                    completion();
                }
            });
        }
    }]; 
}

- (void)saveWithCompletion:(void(^)(void))completion {
    [self performBlock:^{
        NSError *error = nil;
        if ([self save:&error]) {
            NSNumber *contextID = [self.userInfo objectForKey:@"contextID"];
            if (contextID.integerValue == VKCoreDataManagedObjectContextIDMainThread) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    if (completion) {
                        completion();
                    }
                });
            }
            [[self class] logContextSaved:self];
            if (self.parentContext) {
                [self.parentContext saveWithCompletion:completion];
            }
        } else {
            [VKCoreData handleError:error];
            dispatch_async(dispatch_get_main_queue(), ^{
                if (completion) {
                    completion();
                }
            });
        }
    }];
}

只有在保存主线程上下文时才会触发完成。这个解决方案非常完美,但是

当我从服务器获取超过 1000 个实体时,我想并行处理对象,导致更新操作花费太多时间(例如,4500 更新大约 90 秒而不到 1/3 的时间需要 JSON 接收过程,所以大约 60 秒我只是钻 NSManagedObjects)。如果没有 CoreData,使用 dispatch_group_t 将数据划分为子数组并同时在不同的线程中处理它非常容易,但是......有人知道如何使用 CoreData 和 NSManagedObjectContexts 制作类似的东西吗?是否可以在没有 performBlock: 的情况下使用 NSManagedObjectContext 和 NSPrivateQueueConcurrencyType(iOS 5 风格)?保存和合并大约 10 个上下文的最佳方法是什么?谢谢!

【问题讨论】:

  • 你在saveBlock里面做什么?您是否为每个添加的实体保存一次?
  • 基本上我正在更新所有接收到的对象的数据,管理谁被删除/添加,通过简单地枚举和使用接收到的 JSONDictionaries 更新 NSManagedObjects 来更改一些状态。

标签: ios5 core-data grand-central-dispatch nsmanagedobjectcontext


【解决方案1】:

根据您的描述,您似乎正在抓住救命稻草来恢复表现。

Core Data 文件 I/O 性能主要由 SQLite 的单线程特性决定。多个上下文在同一个商店协调器上跳动不会让事情进展得更快。

要提高性能,您需要以不同的方式做事。例如,您可以将后台写入批处理到更大的操作中。 (怎么做?你需要在保存之前在每个 GCD 块中做更多的事情。)你可以使用 Core Data 的调试工具来查看你的获取和保存发出了什么样的 SQL。 (有很多方法可以提高 CD 获取性能,但提高节省的方法较少。)

【讨论】:

  • 我已经在使用 privateBackgroundQueue 将数据保存到磁盘,我的上下文方案如下所示:privateBackgroundDBSavingContext->mainThreadContext->>tempBackgroundContexts。 (-> 表示父级-> 子级),因此在保存 mainThreadContext 后,所有 DB 将使用 privateBackgroundDBSavingContext 存储到磁盘。我会尝试跟踪还有什么可以提高我的数据库性能
【解决方案2】:

好的,在我完成所有我想要的实现后,我发现了以下内容:

dispatch_group_t 具有不同的 PrivateQueues 和 NSManagedObjectContexts 结果:

格式为“实体数/秒”:

  • 333 /6
  • 1447/27
  • 3982/77

单后台线程(NSManagedObjectContext + NSPrivateQueueConcurrencyType + performBlock:)

  • 333 /1
  • 1447/8
  • 3982/47

所以我认为我不应该再试一次了,还有很多其他问题,例如在合并大量上下文(即使在后台)时应用程序冻结。我会尝试其他方法来提高性能。

【讨论】:

    【解决方案3】:

    您可以创建多个上下文并在每个上下文中处理一部分数据...?

    【讨论】:

      猜你喜欢
      • 2015-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多