【问题标题】:Reducing the memory footprint of a function with a lot of autoreleased variables?减少具有大量自动释放变量的函数的内存占用?
【发布时间】:2011-04-22 03:29:28
【问题描述】:

我仍在思考 Objective-C 中内存管理的一些细微差别,并提出了以下我不确定的案例:

+ (NSDecimalNumber*)factorial: (NSDecimalNumber *)l {

    NSDecimalNumber *index = l;
    NSDecimalNumber *running = [NSDecimalNumber one];

    for (; [index intValue] > 1; index = [index decimalNumberBySubtracting:[NSDecimalNumber one]]) {
        running = [running decimalNumberByMultiplyingBy: index];
    }
    return running;
}

在这里,decimalNumberByMultiplyingBy 和 decimalNumberBySubtracting 将创建大量 NSDecimalNumber,据我了解,它们最终会自动释放,但我担心直到那个时候包含的程序会占用大量内存。

我应该在某处引入自动释放池吗? (如果是的话在哪里?)这会对性能产生显着影响(与使用这么多内存的副作用相比)?

自动释放是否适合在这里使用?我是否应该考虑打破循环并在完成后手动释放内存?

这可能是一个 n00b 问题,但我试图了解在这种情况下最佳做法是什么。

【问题讨论】:

  • 注意:由于 NSDecimalNumber 的范围限制,我意识到这不会是计算阶乘的超级有效方法,只是碰巧在我的脑海中出现了这个例子。

标签: objective-c performance memory-management autorelease


【解决方案1】:

确定答案的最佳方法是用几种不同的方式编写它并进行测试。我不认为这会是一个问题,但是,NSDecimalNumbers 将最大约为 100!,而 100 个 NSDecimalNumber 对象可能不会有什么不同。


回答您的其他问题:在重要的情况下,您可以手动释放您的对象。您还可以在该循环内创建一个自动释放池。 Autorelease is super fast.

while(/*condition*/) {
     NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    // code goes here

    [pool drain];
}

【讨论】:

    【解决方案2】:

    您可以在循环中设置一个自动释放池,但为什么要麻烦呢?

    您将无法在此循环中累积那么多对象,因为您正在计算阶乘,NSDecimalNumber 可以拥有的最大指数是 127。

    在循环进行 100 次迭代之前,您将收到溢出错误。

    请注意,每次应用程序通过主运行循环时,主自动释放池都会清空,因此自动释放的值不会停留很长时间。

    【讨论】:

      【解决方案3】:

      最好避免在一次运行循环中创建大量自动释放的大型对象。您似乎已经知道解决方案。您可以使用非自动释放的对象并在使用完它们后释放它们。您还可以为创建大量自动释放对象的代码部分创建自动释放池。当一个对象被自动释放时,它会在封闭的自动释放池被释放/耗尽时被释放。使用自动释放池如下所示:

      NSAutoReleasePool *subPool = [[NSAutoreleasePool alloc] init];
      // Code that generates a bunch of autoreleased objects.
      [subPool release];
      

      但是,在您进行任何优化之前,请运行一些基准测试,看看您是否真的需要优化。我的猜测是您展示的方法不会引起任何问题。但是,假设您正在尝试将您的方法应用于单个循环中的一百万个随机整数的集合。在这种情况下,您可能会从使用自动释放池中受益。

      查看 Apple 的 Cocoa 内存管理编程指南了解更多详情。

      【讨论】:

      • 我的理解是否正确,我无法手动释放由 decimalNumberBySubtracting 创建的对象?当它创建的对象被自动释放时,这会导致问题吗?
      • 是的。如示例代码所示,“手动释放”已自动释放的对象的唯一方法是使用自动释放池。
      • 你是对的。如果您不拥有该对象,则不应释放它。自动释放池会释放对象,所以如果你释放它,它最终会被释放两次。
      • 感谢您的推荐,Apple Dev 内存管理指南正是我所需要的。在我读过的其他内容中,事情变得有点过于简单化了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-21
      • 1970-01-01
      • 2013-03-17
      • 2013-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多