iOS开发Tips3:循环的性能

本文探讨了iOS开发中遍历数组的不同方法,包括for循环、快速遍历、enumerateObjectsUsingBlock和dispatch_apply,分析了它们的性能差异。实验结果显示,enumerate-block性能最低,是快速遍历的近20倍,而NSEnumerator和普通for循环性能接近。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

遍历列表应该是平时开发中最常见的一种操作了。说起遍历效率,相比于其他方面的因素(可维护性,易懂等),也许遍历的效率在你的代码中并不是那么重要。

但我们还是要了解一下从性能方面去考虑遍历这个问题,以便在一写特殊的case下知道怎么着手去优化。


下面是几种常用的遍历方式:

1.  for (NSInteger i = 0 ; i < len; i++)

2. for ( NSObject * o bj in  Array)

3. - (void)enumerateObjectsUsingBlock:(void (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))block 

4.  dispatch_apply( size_t iterations, dispatch_queue_t queue,

DISPATCH_NOESCAPE void (^block)(size_t));

5.NSEnumerator


1. 我们最常用的遍历方式


2. 快速遍历,这种写法在 写法上更直接明了,可以直接拿到数组中的元素


3. 苹果提供的block块遍历, 有以下特点:

    1. 索引和元素均可以返回,其他只返回元素

    2. 并发枚举,也不是说并发就一定高效,当有大量的任务去做的时候,在多核处理器下,对性能的提升比较明显,相反,要是任务很小,它带来的好处可能并不大,在性能比较重要的场景可以试验权衡。


4. Index 顺序不确定,因为它是并行执行的(dispatch_get_global_queue是并行队列)。这里 dispatch_apply如果换成串行队列上,则会依次输出index。

dispathc_apply 是dispatch_sync 和dispatch_group的关联API.它以指定的次数将指定的Block加入到指定的队列中。并等待队列中操作全部完成。


5. 每次被调用时会生成NSEnumerator实例,并指向第一个元素,和链表next指针一样,nextObject方法返回下一个元素,直到元素为nil止。


下面看代码,我们目标是获取到每个元素:

- (void)loop_test
{
    NSArray *sampleItemArray = [self itemArray];
    CFTimeInterval startTime = CFAbsoluteTimeGetCurrent();
   
    //  - - - - - - - - - - - --- - - -- - -- -- - - - -- - -- -

    NSInteger len = [sampleItemArray count];
    
    for (NSInteger i = 0 ; i < len; i++){
        NSObject *obj = sampleItemArray[i];

    }
    NSLog(@"common for-in loop: %.8f", CFAbsoluteTimeGetCurrent() - startTime);
    
    
//  - - - - - - - - - - - --- - - -- - -- -- - - - -- - -- -
    startTime = CFAbsoluteTimeGetCurrent();
    for (NSObject *obj in sampleItemArray){
        
    }
    NSLog(@"fast for-in loop: %.8f", CFAbsoluteTimeGetCurrent() - startTime);
    
//  - - - - - - - - - - - --- - - -- - -- -- - - - -- - -- -

    startTime = CFAbsoluteTimeGetCurrent();
    [sampleItemArray enumerateObjectsUsingBlock:^(NSObject * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
    }];
    NSLog(@"enumerate-block loop: %.8f", CFAbsoluteTimeGetCurrent() - startTime);

//  - - - - - - - - - - - --- - - -- - -- -- - - - -- - -- -

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    startTime = CFAbsoluteTimeGetCurrent();
    dispatch_apply([sampleItemArray count], queue, ^(size_t index) {
        NSObject *obj = sampleItemArray[index];
        
    });
    NSLog(@"dispatch_apply loop: %.8f", CFAbsoluteTimeGetCurrent() - startTime);

//  - - - - - - - - - - - --- - - -- - -- -- - - - -- - -- -

    NSObject *obj = nil;
    
    startTime = CFAbsoluteTimeGetCurrent();
    NSEnumerator *enumerator = [sampleItemArray objectEnumerator];
    while ((obj = [enumerator nextObject])) {
    
    }
    NSLog(@"NSEnumerator loop: %.8f", CFAbsoluteTimeGetCurrent() - startTime);
}
打印结果:

common for loop:      0.00076401

fast for-in loop:     0.00004494

enumerate-block loop: 0.00093901

dispatch_apply loop:  0.00052500

NSEnumerator loop:    0.00072098


结论分析:数据来看
1. 性能最优 的是快速枚举for-in

2. enumerate-block性能最差,是快速枚举的近20倍。

3. NSEnumerator和普通的for循环差别不大,是apply的1.4倍


    


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值