zoukankan      html  css  js  c++  java
  • oc/object-c/ios哪种遍历NSArray/NSDictionary方式快?测试报告

    做app的时候,总免不了要多次遍历数组或者字典。
    究竟哪种遍历方式比较快呢?我做了如下测试:
    首先定义测试用宏:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    #define MULogTimeintervalBegin(INFO) NSTimeInterval start = [NSDate timeIntervalSinceReferenceDate];
    NSTimeInterval duration = 0;
    NSLog(@"MULogTimeintervalBegin:%@", INFO)
     
    #define MULogTimeintervalPauseAndLog(INFO) duration = [NSDate timeIntervalSinceReferenceDate] - start;
    start += duration;
    NSLog(@"%@:%f", INFO, duration);
    duration = 0
    #define TESTSCALE 100000



    接着编写测试代码:
    NSarray:

    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
    - (void)testArray
    {
        NSMutableArray* testArray = [NSMutableArray arrayWithCapacity:TESTSCALE];
        for (NSInteger i = 1; i <= TESTSCALE; ++i) {
            [testArray addObject:[NSString stringWithFormat:@"%ld", i]];
        }
        NSLog(@"init:%ld", [testArray count]);
         
        __block NSMutableString* sum = [NSMutableString stringWithCapacity:TESTSCALE];
         
        MULogTimeintervalBegin(@"ArrayTest");
        NSUInteger count = [testArray count];
        for (NSInteger i = 0; i < count; ++i) {
            [sum appendString:[testArray objectAtIndex:i]];
        }
        [sum setString:@""];
        MULogTimeintervalPauseAndLog(@"for statement");
         
        for(NSString* item in testArray) {
            [sum appendString:item];
        }
        [sum setString:@""];
        MULogTimeintervalPauseAndLog(@"for-in");
         
        [testArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
            [sum appendString:obj];
        }];
        [sum setString:@""];
        MULogTimeintervalPauseAndLog(@"enumerateBlock");
    }


    NSDictionary:

    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
    - (void)testDictionary {
        NSMutableDictionary* testDic = [NSMutableDictionary dictionaryWithCapacity:TESTSCALE];
        for (NSInteger i = 1; i <= TESTSCALE; ++i) {
            [testDic setObject:@"test" forKey:[NSString stringWithFormat:@"%ld", i]];
        }
        NSLog(@"init:%ld", [testDic count]);
         
        __block NSMutableString* sum = [NSMutableString stringWithCapacity:TESTSCALE];
         
        MULogTimeintervalBegin(@"DictionaryTest");
        for (NSString* object in [testDic allValues]) {
            [sum appendString:object];
        }
        [sum setString:@""];
        MULogTimeintervalPauseAndLog(@"for statement allValues");
         
        for (id akey in [testDic allKeys]) {
            [sum appendString:[testDic objectForKey:akey]];
        }
        [sum setString:@""];
        MULogTimeintervalPauseAndLog(@"for statement allKeys");
         
        [testDic enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
            [sum appendString:obj];
        } ];
        MULogTimeintervalPauseAndLog(@"enumeration");
    }



    下面是测试结果:
    Test Case '-[LoopTestTests testArray]' started.
    2012-08-02 17:14:22.061 otest[388:303] init:100000
    2012-08-02 17:14:22.062 otest[388:303] MULogTimeintervalBegin:ArrayTest
    2012-08-02 17:14:22.075 otest[388:303]for statement:0.013108
    2012-08-02 17:14:22.083 otest[388:303]for-in:0.008186
    2012-08-02 17:14:22.095 otest[388:303] enumerateBlock:0.012290
    Test Case '-[LoopTestTests testArray]' passed (0.165 seconds).
    Test Case '-[LoopTestTests testDictionary]' started.
    2012-08-02 17:14:22.273 otest[388:303] init:100000
    2012-08-02 17:14:22.274 otest[388:303] MULogTimeintervalBegin:DictionaryTest
    2012-08-02 17:14:22.284 otest[388:303] for statement allValues:0.010566
    2012-08-02 17:14:22.307 otest[388:303] for statement allKeys:0.022377
    2012-08-02 17:14:22.330 otest[388:303] enumeration:0.023914
    Test Case '-[LoopTestTests testDictionary]' passed (0.217 seconds).

    可以看出对于数组来说,for-in方式遍历速度是最快的,普通风格的for和block方式速度差不多。对于字典来说,allValues方式遍历最快,allKeys和block差不多。
    那么,为什么会这样呢?
    NSArray:

    1
    2
    3
    for (NSInteger i = 0; i < count; ++i) {
            [sum appendString:[testArray objectAtIndex:i]];
    }


    这里由于存在:[objectAtIndex:i]这样的取操作,所以速度会有所下降。

    1
    2
    3
    for(NSString* item in testArray) {
            [sum appendString:item];
    }


    尽管也有取操作,但是绕开了oc的message机制,速度会快一点。也有可能是编译器为了for-in作了优化。
    block为什么会慢一些这个有待研究。
    NSDictionary:

    1
    2
    3
    for (id akey in [testDic allKeys]) {
            [sum appendString:[testDic objectForKey:akey]];
    }


    这个就很明显了,第二种方法多了一次objectForKey的操作。block的话有待研究。



    google了一下,stackoverflow上面有类似的讨论:点击打开链接
    大意是:for-in语法会对容器里面的元素的内存地址建立一个缓冲,遍历的时候从缓冲直接取得元素的地址而不是通过调用方法来获取,所以效率比较高。另外,这也是不能在循环体中修改容器元素的原因之一。

  • 相关阅读:
    使用FormData,进行Ajax请求并上传文件
    oracle视图详解
    Unicode和UTF-8之间的关系
    如何访问tomcat所在服务器的其他盘符的资源。
    React首次渲染过程
    react知识点总结
    WebSocket基础
    gulp 批量添加类名 在一个任务中使用多个文件来源
    Chrome浏览器取消INPUT自动记忆下拉框
    Angular7 Drag and Drop
  • 原文地址:https://www.cnblogs.com/langtianya/p/3917098.html
Copyright © 2011-2022 走看看