我知道有相当多的主题似乎是关于完全相同的事情,但我没有找到一个真正关于我想要的东西。
所以我很好奇,想将 Fast Enumeration 的性能与 NSEnumerator 和 for 循环进行比较。(这是经常被问到的部分)
首先我比较了快速枚举:
for(NSNumber *number in testArray)
{
assert(number);
}
NSE 分子:
NSEnumerator *enumerator = [testArray objectEnumerator];
NSNumber *number;
while (number = [enumerator nextObject])
{
assert(number);
}
循环:
for(NSUInteger i = 0; i < [testArray count]; i++)
{
NSNumber *number = [testArray objectAtIndex:i];
assert(number);
}
我testArray
是一个由 0 到 1,000,000 的 NSNumber 组成的数组,我一个接一个地运行了 100 次测试,并计算了每个测试的平均运行时间。
我也在我的 iPad 2 上运行它们
结果:(所有 100 次运行的平均时间)
- 0.042687s快速枚举
- 0.582072s NSEnumerator
- 0.627318s for 循环
正如预期的那样,Fast Enumeration 是迄今为止最快的,并且 NSEnumerator 仍然比 for 循环快一点,但这是用于枚举退出大型数组
所以这是一个不太常见的问题:
其实我对别的东西很感兴趣:在数组中枚举以比较数组中的每个对象
第一次尝试使用嵌套的 for 循环:
for(int i = 0; i < [testArray count]-1; i++)
{
NSNumber *number = [testArray objectAtIndex:i];
for(int j = i+1; j < [testArray count]; j++)
{
NSNumber *innerLoopNumber = [testArray objectAtIndex:j];
assert(innerLoopNumber);
assert(number);
}
}
对于这些测试,我必须减小数组的大小和运行次数才能在合理的时间内完成它们,因为迭代次数当然会随着 O(n^2) 的增加而增加。所以我用一个包含 5.000 个 NSNumber 的数组运行它们,并重复测试 5 次。
结果:1 次运行7.360645 秒
所以我想,当然,快速枚举应该更快。但是为了实现三角形模式以避免对每对元素进行两次比较,我不得不将外循环中的 Fast Enumeration 与内循环中的 NSEnumerator 混合
for(NSNumber *number in testArray)
{
NSEnumerator *reverseEnumterator = [testArray reverseObjectEnumerator];
NSNumber *innerLoopNumber = reverseEnumterator.nextObject;
while(innerLoopNumber && ![innerLoopNumber isEqualToNumber:number])
{
innerLoopNumber = reverseEnumterator.nextObject;
assert(innerLoopNumber);
assert(number);
}
}
令我惊讶的是,这要慢得多:18.086980s for 1 run
然后我也尝试了一个混合版本,对外部循环使用快速枚举,对内部循环使用 for 循环:
int counter = 0;
for(NSNumber *number in testArray)
{
for(int j = counter +1; j < [testArray count]; j++)
{
NSNumber *innerLoopNumber = [testArray objectAtIndex:j];
assert(innerLoopNumber);
assert(number);
}
counter++;
}
结果:1 次运行7.079600 秒
只比普通的 for 循环快一点。
一个地方的数字:
- 07.360645s for-循环
- 07.079600s混合动力
- 18.086980s快速枚举
所以我想知道,这是为什么呢?快速枚举是否仅在“未中断”时才能正常工作,使用 NSEnumerator 是否会干扰快速枚举?还是我只是遗漏了一些东西而我的方法是错误的?