我阅读了一些关于块和快速枚举以及GCD等的文章。 @Bbum,他写了许多关于GCD和块主题的文章,他说块枚举方法总是比快速枚举方法快或快。你可以阅读他的推理here。
虽然这是一次引人入胜的智力对话,但我同意那些说这实际上取决于手头任务的人的意见。
我有一些任务需要完成,我需要快速,便宜,高效地完成这些任务。 Apple为我们想要枚举数组的方式提供了 许多 选项,但我不确定选择哪个。
for (id obj in array)
{
/* Do something with |obj|. */
}
[array enumerateObjectsUsingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
/* Do something with |obj|. */
}];
[array enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
/* Do something with |obj|. */
}];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_apply([array count], queue, ^(size_t idx) {
id obj = [array objectAtIndex: idx];
/* Do something with |obj|. */
});
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0);
dispatch_async(queue, ^(void) {
dispatch_apply([array count], queue, ^(size_t idx) {
id obj = [array objectAtIndex: idx];
/* Do something with |obj|. */
});
});
或者可能包含NSBlockOperation
s或NSOperationQueue
的内容?
TIA,Alex。
答案 0 :(得分:44)
说真的 - 除非你有一个可衡量的性能问题,否则这个特殊的选择不应该占用你的时间而不是回答这些模式中哪一个最适合我的项目风格? < / p>
注意:通过从串行执行到并发执行来解决性能问题通常会导致两个问题;表现&amp;并发性。
答案 1 :(得分:4)
这实际上取决于手头的任务。
一次处理多个迭代需要生成线程。如果迭代中的逻辑是可并行化的并且花费的时间比生成线程所花费的时间多,那么使用线程。另外,如果数组中有这么多项,那么生成一个线程所花费的时间少于遍历整个数组,将数组分成几块并并行处理它们。
否则,产生线程来迭代数组是开销。即使操作系统为您处理,它仍然 需要产生它们。这需要时间和资源以及运行时的上下文切换(取决于可用的CPU数量,负载,调度程序等)。
这一切都归结为产生一个新线程所花费的时间比走遍整个阵列要长。您可以使用分析工具找到它。
答案 2 :(得分:2)
如果您观看WWDC视频&#34; iOS7中的隐藏开发宝石&#34; (这个问题比授予的视频要早),你会发现使用GCD可以更好地实现简单的for循环枚举:
[array enumerateObjectsWithOptions: NSEnumerationConcurrent usingBlock: ^(id obj, NSUInteger idx, BOOL *stop) {
/* Do something with |obj|. */
}];
虽然它确实取决于手头的任务,并且运输软件是最重要的,但是当你的应用程序开始扩展时,肯定有一些简单的方法可以防止性能问题成为未来的技术债务问题。例如,您可能拥有较大的网络获取结果。从这个结果中,您可能必须遍历获取的对象并更新一些模型或一系列模型(而不是Core Data模型,因为Core Data不是线程安全的!必须采取额外的措施来在多个线程上使用Core Data。这是如果您正在考虑从多线程方案开发Core Data,那么您将需要研究一个深层主题。考虑到您没有对UI执行更新(因为这不是您想要从主线程执行的操作),您可以使用此方法充分利用设备的硬件。它不是一次只使用一个核心的for循环,而是完全利用并行的可用核心,从而提高性能并可能几乎将执行时间减半。如果不考虑您正在枚举的数组以及您在块中执行的任务,这不是您想要做的事情,但如果仔细使用,这对于各种情况都很有用。