25

在循环操作时将大量自动释放的对象放入自动释放池中是一种很好的做法。我发现有人将@autoreleasepool 放入循环,但其他人将循环放入@autoreleasepool。

1:

while ([rs next]) {
    @autoreleasepool {
        NSDictionary *dict = [self dictFromXX];
        //...
    }
}

2:

@autoreleasepool {
    while ([rs next]) {
        NSDictionary *dict = [self dictFromXX];
        //...
    }
}

哪个更好?或者代码1和2之间有什么区别?

谢谢!

4

6 回答 6

33

在您的第一个示例中,每次迭代都会耗尽池。如果迭代的主体涉及大量自动释放的对象,这是有道理的。

第二个示例只会在循环后耗尽池一次。

因此,如果循环的内部导致内存膨胀,请选择选项一。如果整个循环的内存膨胀是可以接受的,那么循环然后使用选项二。

于 2012-04-12T10:09:00.440 回答
3

在第一个示例中,autoreleasepool 在迭代开始时创建,并在迭代结束时被耗尽。在第二种情况下,池被创建一次,只有在循环完成后才被销毁。如果您使用第二种变体,那么您可能会获得很大的内存开销,因为所有自动释放的对象仅在最后才被释放。但是,您应该考虑需要处理的数据量。在大多数情况下,第二个变体是更优选的。

于 2012-04-12T10:05:36.243 回答
1

我会选择第 2 版。

当块完成时,@autoreleasepool块将释放所有接收到的对象autorelease。这将需要一些时间,因为它需要一些 cpu 周期,并且根据对象的不同,使用的时间可能比预期的要高得多。

我认为 custom@autoreleasepool仅在处理 > 20MB 的许多数据或在非主线程中处理 Data 时才有意义。

所以。我建议避免“短” @autoreleasepool。因为它可能会减慢您的执行速度。

于 2012-04-12T10:03:18.257 回答
0

这是使用 Core Data 和 autoreleasepools 的另一种方法:

使用对您很重要的高效导入数据的非常大的分层数据集测试核心数据Wrap the contents of the outer loop in an NSAutoreleasePool init/release and NSManagedObjectContext save是解决方案。

于 2012-04-12T10:00:16.637 回答
0

取决于将释放多少待处理的项目。图像自动释放池就像你的垃圾一样,放置未使用的东西,稍后再扔。

于 2012-04-12T10:10:07.627 回答
0

@autoreleasepool块比直接使用实例更有效NSAutoreleasePool;即使您不使用 ARC,也可以使用它们。- NSAutoreleasePool 类参考

您通常不需要自动释放池,如果您这样做是因为您处于循环中并自动释放大量对象,那么选项 1 比 2 更有意义,因为您试图避免循环创建的尖峰。使用选项 2 的时间是如果没有设置自动释放池(例如,如果您在后台或在后台执行选择器+load),但无论如何您都应该尝试使用 GCD。

总之,如果您没有很长的方法并且需要在自动释放池中包装一个循环,那么在大多数情况下选择选项 1。如果在没有设置自动释放池的情况下调用该方法,那么@autorelease首先需要做的是。

于 2012-04-12T10:22:09.697 回答