刷新领域的成本是多少?

时间:2016-03-24 14:37:16

标签: multithreading realm

我已阅读文档并了解在许多情况下您无需在refresh实例上手动调用Realm。但是,在这种非常常见的情况下,事实证明这是必要的,因为完成块可能会在下一个运行循环开始之前查询Realm。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [[RLMRealm defaultRealm] transactionWithBlock:^{
        // Add some RLMObjects
    }];

    if (completion) {
        dispatch_async(dispatch_get_main_queue(), ^{
            [[RLMRealm defaultRealm] refresh]; // necessary if it queries realm
            completion();
        });
    }
});

我认为通过在后台线程上执行写操作我是一个好公民,但现在我必须调用refresh,我想知道这个调用中涉及的开销是否会使得后台处理。

所以我的问题是:

1)在refresh上调用Realm会有什么性能成本?

2)在这种模式中只添加一个对象可能是 无意义。在这个模式中添加了多少个对象后,我会看到比同步在主线程上执行写入事务的替代方案更有优势吗?

1 个答案:

答案 0 :(得分:5)

非常棒的问题!

  

1)在refresh上调用Realm会有什么性能成本?

TL;博士;刷新不是那么贵

成本将与该线程上提升的Realm实例支持的实时“访问者”的数量成比例线性。 Realm Objective-C中的访问者是RLMObject s,RLMArrayRLMResult s。

由于Realm使用了MVCC versioning system,类似于git的内部工作,调用-[RLMRealm refresh]是将Realm的“当前事务指针”提升到最新稳定状态的问题,就像{{ {1}}操作。

值得注意的是,对于具有runloop并且git pull设置为autorefresh的线程上的Realms(主线程上的Realms通常就是这种情况),YES将是在runloop的每次迭代中自动调用。

因此,在绝大多数情况下,刷新Realm的性能影响可以忽略不计,除非您在该线程上有非常大量的实时“访问者”。

  

2)在这种模式中只向一个领域添加一个对象可能毫无意义。在这个模式中添加了多少个对象后,我会看到比同步在主线程上执行写入事务的替代方案更有优势吗?

TL;博士;在后台执行写入更安全

在绝大多数没有争用的情况下,在主线程上执行写事务的开销将低于平滑UI所需的1/60秒的阈值。 然而在Realm中写入阻塞,这意味着如果在后台同时发生大量写入事务,这将在同时从主线程写入时阻塞主线程,这不太理想,因为它会导致UI口吃或阻塞。

出于这个原因,我们建议所有写入事务,无论多小和多快,都要在后台线程上执行,除非您确定不会有任何争用。

我意识到在后台线程上执行写操作会因Realm对访问器的严格线程限制执行而变得复杂,这就是我们跟踪为异步写入添加API的原因,允许在#3136中跨线程安全地移交访问器。

由于Realm中的读取操作未被其他读取或写入阻止(感谢上面提到的MVCC!),在任何线程上执行这些操作都是完全可以接受的。