Benchmarking

Objective-C 中使用 Benchmarking 测量效率


第一发:CFAbsoluteTimeGetCurrent

staticsize_tconstcount=1000;

staticsize_tconstiterations=10000;

idobject=@"";

做这个 benchmarking 很简单:代码运行前记录一次时间,运行后记录一次,然后比较时间差

for 循环用来让 count 和 iterations 递增。每个循环体都被 @autoreleasepool 包裹,用来降低内存占用。

    CFTimeInterval startTime = CACurrentMediaTime();

        for(size_ti =0; i

            @autoreleasepool {

                NSMutableArray*mutableArray = [NSMutableArrayarray];

                for(size_tj =0; j

                    [mutableArrayaddObject:object];

                }

            }

        }

    CFTimeInterval endTime = CACurrentMediaTime();

    NSLog(@"Total Runtime: %g s", endTime - startTime);

第二发:dispatch_benchmark

dispatch_benchmark 是 libdispatch (Grand Central Dispatch) 的一部分。但严肃地说,这个方法并没有被公开声明,所以你必须要自己声明:

extern uint64_t dispatch_benchmark(size_t count, void(^block)(void));

uint64_t t = dispatch_benchmark(iterations, ^{       

    @autoreleasepool {           

            NSMutableArray *mutableArray = [NSMutableArray array];           

            for (size_t i = 0; i < count; i++) {               

            [mutableArray addObject:object];           

            }       

    }   

});   

NSLog(@"[[NSMutableArray array] addObject:] Avg. Runtime: %llu ns", t);

NSMutableArray array 对决 arrayWithCapacity:!


 uint64_t t_0 = dispatch_benchmark(iterations, ^{

        @autoreleasepool {

            NSMutableArray *mutableArray = [NSMutableArray array];

            for(size_ti =0; i

                [mutableArrayaddObject:object];

            }

        }

    });

    NSLog(@"[[NSMutableArray array] addObject:] Avg. Runtime: %llu ns", t_0);


    uint64_t t_1 = dispatch_benchmark(iterations, ^{

        @autoreleasepool {

            NSMutableArray *mutableArray = [NSMutableArray arrayWithCapacity:count];

            for(size_ti =0; i

                [mutableArrayaddObject:object];

            }

        }

    });

    NSLog(@"[[NSMutableArray arrayWithCapacity] addObject:] Avg. Runtime: %llu ns", t_1);

[[NSMutableArray array] addObject:]: Avg. Runtime 26119 ns

[[NSMutableArray arrayWithCapacity] addObject:] Avg. Runtime: 24158 ns

经过大规模样本的测试,用 capacity 与否造成了 7% 的效率差异。


Benchmarking 常识指南

知道你要解答的是什么问题。 虽然我们始终致力于用思考去代替神奇的思维,但我们必须保护自己免受科学方法的淹没,也不应该支持不完整的推理。得出结论之前,花一些时间去理解在大背景下你的结果到底意味着什么。

不要在你 app 的提交代码中加入 benchmarking。 注意,dispatch_benchmark 可能会导致 app 被 App Store 拒绝,benchmark 代码不应该被加到终极提交的产品中。Benchmarking 应该被分离到单独的项目分支或独立的测试用例中。

使用 Instruments 来获得更有用的结果。 知道了一系列计算过程的运行绝对时间确实有价值,但可能不足以为减少内存使用提供完善的参考。使用 Instruments 来分析有疑问代码的栈调用和内存用量,你会对这段代码到底发生了什么有更好地理解。

在真实设备上 benchmark。 像其他任何效率测量工具一样,测量终究要在真正的机器上跑一跑。大多数情况下模拟器和真实设备的效率测量结果是一致的,但以防万一还是值得这么做的。

不要过早优化。 这句话怎么强调也不过分。 工程师的普遍倾向是在发现真正的原因之前过分关注他们认为的“慢代码”。即使是老手也很容易把应用的瓶颈预测错误。不要浪费时间在追赶影子上。让 Instruments 告诉你你的应用到底哪里花费了最多的时间。

你可能感兴趣的:(Benchmarking)