NSEnumerator 性能与 Cocoa 中的 for 循环
我知道,如果您有一个修改循环中项目计数的循环,则在集合上使用 NSEnumerator 是确保代码崩溃的最佳方法,但是我想了解 NSEnumerator 类之间的性能权衡只是一个老派的 for 循环
I know that if you have a loop that modifies the count of the items in the loop, using the NSEnumerator on a set is the best way to make sure your code blows up, however I would like to understand the performance tradeoffs between the NSEnumerator class and just an old school for loop
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在 Objective-C 2.0 中使用新的 for (... in ...) 语法通常是迭代集合的最快方法,因为它可以在堆栈上维护一个缓冲区并获取批量的项目进去。
使用 NSEnumerator 通常是最慢的方法,因为它经常复制正在迭代的集合; 对于不可变集合,这可能很便宜(相当于
-retain
),但对于可变集合,它可能会导致创建不可变副本。进行您自己的迭代 - 例如,使用
-[NSArray objectAtIndex:]
- 通常会介于两者之间,因为虽然您不会有潜在的复制开销,但您也不会获得批量的来自底层集合的对象。(PS - 这个问题应该标记为 Objective-C,而不是 C,因为
NSEnumerator
是一个 Cocoa 类,并且新的for (... in ...)
语法特定于 Objective-C。)Using the new
for (... in ...)
syntax in Objective-C 2.0 is generally the fastest way to iterate over a collection because it can maintain a buffer on the stack and get batches of items into it.Using
NSEnumerator
is generally the slowest way because it often copies the collection being iterated; for immutable collections this can be cheap (equivalent to-retain
) but for mutable collections it can cause an immutable copy to be created.Doing your own iteration — for example, using
-[NSArray objectAtIndex:]
— will generally fall somewhere in between because while you won't have the potential copying overhead, you also won't be getting batches of objects from the underlying collection.(PS - This question should be tagged as Objective-C, not C, since
NSEnumerator
is a Cocoa class and the newfor (... in ...)
syntax is specific to Objective-C.)运行测试几次后,结果几乎是一样的。 每个测量块连续运行 10 次。
在我的例子中,结果从最快到最慢:
for 和 while 循环几乎相同。
tmp
是一个NSArray
,包含 100 万个从 0 到 999999 的对象。整个代码:
ViewController.h
ViewController.m
MyTestfile.m
有关更多信息,请访问: Apple“关于使用 Xcode 进行测试”
After running the test several times, the result is almost the same. Each measure block runs 10 times consecutively.
The result in my case from the fastest to the slowest:
The for and while loop is almost the same.
The
tmp
is anNSArray
which contains 1 million objects from 0 to 999999.The whole code:
ViewController.h
ViewController.m
MyTestfile.m
For more information visit: Apples "About Testing with Xcode"
他们非常相似。 在 Objective-C 2.0 中,大多数枚举现在默认为
NSFastEnumeration
,它创建一个集合中每个对象的地址缓冲区,然后可以传递该缓冲区。 与经典 for 循环相比,您节省的一个步骤是不必每次在循环内调用objectAtIndex:i
。 您正在枚举的集合的内部实现了快速枚举,而无需调用objectAtIndex:i 方法
。缓冲区是您在枚举时无法改变集合的部分原因,对象的地址将更改并且构建的缓冲区将不再匹配。
作为奖励,2.0 中的格式看起来和经典的 for 循环一样漂亮:
阅读以下文档以深入了解:
NSFastEnumeration 协议参考
They are very similar. With Objective-C 2.0 most enumerations now default to
NSFastEnumeration
which creates a buffer of the addresses to each object in the collection that it can then deliver. The one step that you save over the classic for loop is not having to callobjectAtIndex:i
each time inside the loop. The internals of the collection you are enumerating implement fast enumeration with out callingobjectAtIndex:i method
.The buffer is part of the reason that you can't mutate a collection as you enumerate, the address of the objects will change and the buffer that was built will no longer match.
As a bonus the format in 2.0 looks as nice as the classic for loop:
Read the following documentaion to go deeper:
NSFastEnumeration Protocol Reference