在循环操作中将大量自动释放的对象放入autoreleasepool中是一种很好的做法。我发现有人把@autoreleasepool放在循环中,但其他人把循环放在@autoreleasepool中。
1:
while ([rs next]) {
@autoreleasepool {
NSDictionary *dict = [self dictFromXX];
//...
}
}
2:
@autoreleasepool {
while ([rs next]) {
NSDictionary *dict = [self dictFromXX];
//...
}
}
哪个更好?或者代码1和2之间有什么区别?
谢谢!
答案 0 :(得分:29)
在每次迭代的第一个示例中,池都已耗尽。如果迭代的主体涉及大量自动释放的对象,这是有道理的。
第二个例子只会在循环后消耗池一次。
因此,如果循环的内部导致内存膨胀,那么请选择第一个选项。如果整个循环中的内存膨胀是可接受的,则循环然后使用选项2。
答案 1 :(得分:3)
在第一个示例中,autoreleasepool是在迭代开始时创建的,并且已经耗尽并且迭代结束。 在第二种情况下,池创建一次,并且仅在循环完成后销毁。如果您使用第二个变体,那么您可以获得大量内存开销,因为所有自动释放的对象仅在结尾处被释放。但是,您应该考虑需要处理的数据量。在大多数情况下,第二种变体是更优选的。
答案 2 :(得分:1)
我会选择第2版。
当块完成时,@autoreleasepool
块将释放收到autorelease
的所有对象。这需要时间,因为它需要一些cpu周期,并且根据对象,使用的时间可能比预期的要高得多。
我认为自定义@autoreleasepool
仅在处理许多数据时才有意义> 20MB或在非主线程中使用数据。
因此。我建议避免“短”@autoreleasepool
。因为它可能会减慢你的执行速度。
答案 3 :(得分:0)
以下是Core Data与autoreleasepools的不同方法:
Testing Core Data with very big hierarchical data sets的{p> Efficiently Importing Data 对你来说很重要的是Wrap the contents of the outer loop in an NSAutoreleasePool init/release and NSManagedObjectContext save
解决方案。
答案 4 :(得分:0)
取决于将释放多少待处理项目。 Autorelease Pool就像你的垃圾一样,把未使用过的东西放进去的图片。
答案 5 :(得分:0)
@autoreleasepool
块比直接使用NSAutoreleasePool
的实例更有效;即使您不使用ARC,也可以使用它们。 - NSAutoreleasePool Class Reference
您通常不需要自动释放池,如果您这样做是因为您处于循环中并自动释放大量对象,那么当您尝试避免循环正在创建的峰值时,选项1比2更有意义。使用选项2的时间是,如果没有设置自动释放池(如果您在后台执行选择器,例如在+load
中),但您应该尝试使用GCD。
总之,如果您没有很长的方法并且需要在自动释放池中包装循环,那么在大多数情况下请选择选项1。如果在没有设置自动释放池的情况下调用该方法,那么@autorelease
必须是第一件事。