【问题标题】:@autoreleasepool in loop or loop in @autoreleasepool?@autoreleasepool 在循环中还是在@autoreleasepool 中循环?
【发布时间】:2012-04-12 18:30:59
【问题描述】:

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

1:

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

2:

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

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

谢谢!

【问题讨论】:

标签: iphone objective-c


【解决方案1】:

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

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

      我会选择第 2 版。

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

      我认为自定义@autoreleasepools 仅在处理大于 20MB 的数据或在非主线程中处理数据时才有意义。

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

      【讨论】:

      • 我不明白,释放的总CPU周期将是相同的,因为最终要释放的总对象是相同的。您是在谈论执行自动释放池检查的开销吗?我不确定那里的开销。
      • @HelinWang 经常耗尽内存意味着在 NSAutoreleasePool 上浪费 CPU 周期。
      • @Andy 这就是我的评论要问的:为什么它会经常耗尽内存? ---“最终要释放的总对象是一样的”
      • @HelinWang 因为\@autoreleasepool 本质上会创建额外的NSAutoreleasePool 并调用NSAutoreleasePool.drain()。当然有开销。这取决于具体情况。
      【解决方案4】:

      这是一种不同的方法,使用 Core Data 和自动释放池:

      Testing Core Data with very big hierarchical data setsEfficiently Importing Data Wrap the contents of the outer loop in an NSAutoreleasePool init/release and NSManagedObjectContext save 解决方案对您来说很重要。

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-03-12
            • 2011-12-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多