Objective-C空数组性能

Gri*_*ess 1 collections objective-c

我有一个应用程序,每一步迭代一个数组,当数组为空时,我似乎得到惊人的缓慢结果.所以,我调查了一些类似的后续测试:

NSMutableArray* ar = [NSMutableArray array];
double time = CFAbsoluteTimeGetCurrent();
for (int i = 0; i < 10000; i++)
{
    for (NSObject* obj in ar)
    {
        [obj retain];
        [obj release];
    }
}
time = CFAbsoluteTimeGetCurrent() - time;   
printf("Empty Time: %1.12f", time / 10000.0f);

time = CFAbsoluteTimeGetCurrent();
for (int i = 0; i < 10000; i++)
{
    if ([ar count] > 0)
    {
        for (NSObject* obj in ar)
        {
            [obj retain];
            [obj release];
        }
    }
}
time = CFAbsoluteTimeGetCurrent() - time;   
printf("Checked Time: %1.12f", time / 10000.0f);
Run Code Online (Sandbox Code Playgroud)

我尝试了100 | 1,000 | 10,000次迭代间隔,结果如下:

Empty Time: 0.000000039935          //100
Checked Time: 0.000000020266        //100
Empty Time: 0.000000018001          //1000
Checked Time: 0.000000011027        //1000
Empty Time: 0.000000015503          //10000
Checked Time: 0.000000008899        //10000
Run Code Online (Sandbox Code Playgroud)

奇怪的是,这表明使用简单计数检查可以显着提高低迭代运行的性能(可能是因为缓存方案).这对我来说绝对令人惊讶,因为我期望Objective-C编译/运行时在执行foreach循环时已经进行了此检查!有没有人知道为什么会出现这种情况,如果有任何方法可以从这个循环设置中挤出更多的性能?谢谢!

bbu*_*bum 7

空数组在典型的Cocoa程序中并不常见,也不会迭代数千次的空数组.

如果看到空数组的枚举在仪器中显示为CPU周期的重要消费者,那将是特别令人惊讶的.

鉴于Foundation和Core Foundation针对现实世界的性能模式进行了优化,因此不会进行0计数检查也就不足为奇了.

但是,如果你真的必须迭代一个空数组数十亿次,最快的方法是使用一个块:

time = CFAbsoluteTimeGetCurrent();
[ar enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    [obj retain];
    [obj release];
}];
Run Code Online (Sandbox Code Playgroud)

我将您的代码粘贴到Foundation工具的main()中,并在相对较新的MacBook Pro上获得:

     Empty Time: 0.000000019896
   Checked Time: 0.000000007498
     Block Time: 0.000000000298
Run Code Online (Sandbox Code Playgroud)

当然,而不是空数组,只需使用nil.即我之后第二次做了所有的测试ar = nil;.

ar = nil;
time = CFAbsoluteTimeGetCurrent();
for (int i = 0; i < 10000; i++)
{
    for (NSObject* obj in ar)
    {
        [obj retain];
        [obj release];
    }
}
... etc ...


      Empty Time: 0.000000019902
    Checked Time: 0.000000007999
      Block Time: 0.000000000298
  nil Empty Time: 0.000000015599
nil Checked Time: 0.000000004703
  nil Block Time: 0.000000000000
Run Code Online (Sandbox Code Playgroud)

但总的来说,如果你的数据结构那么复杂,并且你在每个帧渲染上对它们进行了大量的反击,那么我建议可以按顺序使用不同的数据结构.

当然,只有你实际上使用了仪器来对代码进行采样并且正在优化占据整个CPU周期的很大一部分的东西.

  • 在设备上与Snow Leopard上的行为可能会有所不同. (4认同)