首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Cocoa中的NSEnumerator性能与for循环

Cocoa中的NSEnumerator性能与for循环
EN

Stack Overflow用户
提问于 2008-08-28 18:16:54
回答 3查看 6.9K关注 0票数 19

我知道,如果您有一个修改循环中项目计数的循环,那么在集合上使用NSEnumerator是确保代码爆炸的最好方法,但是我想了解一下NSEnumerator类和一个旧的for循环之间的性能权衡。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2008-08-28 19:59:49

在Objective-C2.0中使用新的for (... in ...)语法通常是迭代集合的最快方法,因为它可以在堆栈上维护一个缓冲区,并将成批的项放入其中。

使用NSEnumerator通常是最慢的方式,因为它经常复制要迭代的集合;对于不可变的集合,这可能很便宜(相当于-retain),但对于可变的集合,它可能会导致创建不可变的副本。

进行自己的迭代-例如,使用-[NSArray objectAtIndex:] -通常介于两者之间,因为虽然您不会有潜在的复制开销,但您也不会从底层集合中获得批量对象。

(PS -这个问题应该标记为Objective-C,而不是C,因为NSEnumerator是一个Cocoa类,并且新的for (... in ...)语法特定于Objective-C。)

票数 27
EN

Stack Overflow用户

发布于 2015-06-09 06:47:16

在多次运行测试之后,结果几乎相同。每个测量块连续运行10次。

在我的例子中,结果从最快到最慢:

  1. For..in ( sec)
  2. While ) (0.006 sec)
  3. While (testPerformanceExample3) (0.026 sec)
  4. While (testPerformanceExample1) (0.027 sec)
  5. Enumeration sec)

testPerformanceExample3()testPerformanceExample4 (testPerformanceExample2) (0.067 #en4#

for和while循环几乎是相同的。

tmp是一个NSArray,它包含从0到999999的100万个对象。

代码语言:javascript
复制
- (NSArray *)createArray
{
    self.tmpArray = [NSMutableArray array];
    for (int i = 0; i < 1000000; i++)
    {
        [self.tmpArray addObject:@(i)];
    }
    return self.tmpArray;
}

完整的代码:

ViewController.h

代码语言:javascript
复制
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (strong, nonatomic) NSMutableArray *tmpArray;
- (NSArray *)createArray;

@end

ViewController.m

代码语言:javascript
复制
#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self createArray];
}

- (NSArray *)createArray
{
    self.tmpArray = [NSMutableArray array];
    for (int i = 0; i < 1000000; i++)
    {
        [self.tmpArray addObject:@(i)];
    }
    return self.tmpArray;
}

@end

MyTestfile.m

代码语言:javascript
复制
#import <UIKit/UIKit.h>
#import <XCTest/XCTest.h>

#import "ViewController.h"

@interface TestCaseXcodeTests : XCTestCase
{
    ViewController *vc;
    NSArray *tmp;
}

@end

@implementation TestCaseXcodeTests

- (void)setUp {
    [super setUp];
    vc = [[ViewController alloc] init];
    tmp = vc.createArray;
}

- (void)testPerformanceExample1
{
    [self measureBlock:^{
        for (int i = 0; i < [tmp count]; i++)
        {
            [tmp objectAtIndex:i];
        }
    }];
}

- (void)testPerformanceExample2
{
    [self measureBlock:^{
        [tmp enumerateObjectsUsingBlock:^(NSNumber *obj, NSUInteger idx, BOOL *stop) {
           obj;
        }];
    }];
}

- (void)testPerformanceExample3
{
    [self measureBlock:^{
        for (NSNumber *num in tmp)
        {
            num;
        }
    }];
}

- (void)testPerformanceExample4
{
    [self measureBlock:^{
        int i = 0;
        while (i < [tmp count])
        {
            [tmp objectAtIndex:i];
            i++;
        }
    }];
}

@end

欲了解更多信息,请访问:Apples "About Testing with Xcode"

票数 5
EN

Stack Overflow用户

发布于 2008-08-28 18:37:28

它们非常相似。在Objective-C2.0中,大多数枚举现在默认为NSFastEnumeration,它为集合中的每个对象创建一个地址缓冲区,然后它可以交付该缓冲区。与传统的for循环相比,您节省的一个步骤是不必每次在循环内调用objectAtIndex:i。您正在枚举的集合的内部实现快速枚举,而不调用objectAtIndex:i method

缓冲区是您不能在枚举时改变集合的部分原因,对象的地址将会更改,构建的缓冲区将不再匹配。

作为额外的好处,2.0中的格式看起来和经典的for循环一样好:

代码语言:javascript
复制
for ( Type newVariable in expression ) { 
    stmts 
}

请阅读以下文档以深入了解:NSFastEnumeration Protocol Reference

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32986

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档