关于C#:NSEnumerator性能与可可中的for循环

NSEnumerator performance vs for loop in Cocoa

我知道,如果您有一个循环来修改循环中项目的计数,则在集合上使用NSEnumerator是确保代码爆炸的最佳方法,但是我想了解NSEnumerator类之间的性能折衷 还有一所老学校


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

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

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

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


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

在我的情况下,结果从最快到最慢:

  • For..in(testPerformanceExample3)(0.006秒)
  • While(testPerformanceExample4)(0.026秒)
  • For(;;)(testPerformanceExample1)(0.027秒)
  • 枚举块(testPerformanceExample2)(0.067秒)
  • for和while循环几乎相同。

    comparation between iterations

    tmpNSArray,其中包含1百万个对象,范围从0到999999。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    - (NSArray *)createArray
    {
        self.tmpArray = [NSMutableArray array];
        for (int i = 0; i < 1000000; i++)
        {
            [self.tmpArray addObject:@(i)];
        }
        return self.tmpArray;
    }

    整个代码:

    ViewController.h

    1
    2
    3
    4
    5
    6
    7
    8
    #import <UIKit/UIKit.h>

    @interface ViewController : UIViewController

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

    @end

    ViewController.m

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    #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

    有关更多信息,请访问:苹果公司"关于使用Xcode进行测试"


    它们非常相似。现在,使用Objective-C 2.0时,大多数枚举默认为NSFastEnumeration,这将为该集合中的每个对象创建一个地址缓冲区,然后可以传递该地址。通过经典的for循环保存的一个步骤是不必在循环内每次都调用objectAtIndex:i。您要枚举的集合的内部实现了快速枚举,而无需调用objectAtIndex:i method

    缓冲区是您无法在枚举时对集合进行变异的部分原因,对象的地址将更改,并且已建立的缓冲区将不再匹配。

    另外,2.0中的格式看起来像经典的for循环一样好:

    1
    2
    3
    for ( Type newVariable in expression ) {
        stmts
    }

    阅读以下文档以更深入了解:
    NSFastEnumeration协议参考


    推荐阅读

      python怎么打包整个项目

      python怎么打包整个项目,环境,标准,项目,培训,工作,工具,脚本,状况,以上,版

      python3中如何创建集合

      python3中如何创建集合,数据,培训,元素,类型,字符串,列表,对象,括号,逗号,

      python怎么循环输入

      python怎么循环输入,培训,语句,条件,双数,表达式,详解,两者,命令,下面,次数

      python循环怎么写

      python循环怎么写,培训,语句,条件,双数,表达式,详解,两者,命令,下面,次数,py

      python定时修改数据库

      python定时修改数据库,时间,服务,培训,单位,代码,标准,线程,操作,时间差,进

      python集合要怎么用

      python集合要怎么用,培训,数字,数据,元素,方法,错误,语法,表示,类型,结果,py

      python空集合如何表示

      python空集合如何表示,数据,培训,表示,函数,类型,嵌套,赋值,括号,序列,字典

      python如何退出循环

      python如何退出循环,培训,代码,语句,条件,嵌套,序列,剩余,最小,以上,语言,br

      python怎么写循环

      python怎么写循环,培训,语句,条件,双数,表达式,详解,两者,命令,下面,次数,py

      python集合的并集操作

      python集合的并集操作,培训,操作,参数,更多,语法,符号,实例,元素,以上,两个