可可:为什么for-each比循环更快?

NOr*_*der 3 cocoa for-loop

我的应用程序通过两种方式阅读所有联系人:

for循环:

    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent ();
    long count = macContact.addressBook.people.count;
    for(int i=0;i<count;++i){
        ABPerson *person = [macContact.addressBook.people objectAtIndex:i];
        NSLog(@"%@",person);
    }
    NSLog(@"%f",CFAbsoluteTimeGetCurrent() - startTime);
Run Code Online (Sandbox Code Playgroud)

的for-each

    CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent ();
    for(ABPerson *person in macContact.addressBook.people){
        NSLog(@"%@",person);
    }
    NSLog(@"%f",CFAbsoluteTimeGetCurrent() - startTime);
Run Code Online (Sandbox Code Playgroud)

for-each只花了4秒钟在地址簿中列举5000人,而for循环用了10分钟来完成同样的工作.

我想知道为什么性能会有很大差异?

Lil*_*ard 5

性能的差异几乎肯定与macContact.addressBook.people零件有关.你每次都通过for循环调用它,但只有一次使用for-each循环.我猜要么addressBookpeople属性没有返回每次缓存数据,而是新的数据.

尝试使用

NSArray *people = macContact.addressBook.people;
for (int i = 0; i < [people count]; i++) {
    NSLog(@"%@", [people objectAtIndex:i];
}
Run Code Online (Sandbox Code Playgroud)

您可能会发现性能再次非常相似.


也就是说,for-each比一般情况更快.原因是因为for循环通过循环(-objectAtIndex:)调用每次传递的方法发送,而for-each可以通过大批量获取对象来更有效地获取对象.

在更新版本的操作系统中,您可以更进一步,使用基于块的枚举方法.这看起来像

[macContact.addressBook.people enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL stop){
    NSLog(@"%@", obj);
}];
Run Code Online (Sandbox Code Playgroud)

对于NSArrays,它应该具有与for-each循环非常相似的性能.对于其他数据结构(如字典),此样式可以更快,因为它可以随键获取值(而for-each仅为您提供键并要求您使用消息send来获取值).