【问题标题】:Creating autorelease objects in iPhone Development在 iPhone 开发中创建自动释放对象
【发布时间】:2010-01-05 22:16:12
【问题描述】:

我需要创建一些 NSDecimalNumber objects 对象作为我的应用程序的一部分(因为我需要它们提供的计算精度),但我注意到在计算中它们返回 NSDecimalNumber 对象,这些对象可能是自动释放的。

我的问题是,这在我可能进行大量计算的 iPhone 应用程序中是否存在潜在问题。

这个问题不仅仅与 NSDecimalNumber 有关,还与在开发 iPhone 应用程序的过程中有时不可避免地创建自动释放对象有关。

我们将不胜感激地收到有关这一点的任何详细答案。

【问题讨论】:

    标签: iphone objective-c memory autorelease nsdecimalnumber


    【解决方案1】:

    请记住,您可以创建自己的 NSAutoreleasePool 对象。

    例如:

    for (int i = 0; i < 1000; ++i) {
      NSAutoreleasePool * p = [[NSAutoreleasePool alloc] init];
      for (int j = 0; j < 1000; ++j) {
        NSString * s = [NSString stringWithFormat:@"%d,%d", i, j];
        NSLog(@"%@", s);
      }
      [p release];
    }
    

    如果你这样做,你一次在内存中永远不会有超过 1000 个这样的字符串。

    【讨论】:

      【解决方案2】:

      是的,在 iPhone 上创建大量自动释放的实例会产生内存问题,尤其是在紧密循环中,这就是为什么我倾向于尽可能避免它们。您可以创建自己的自动释放池来管理它,但它们也会增加一些性能开销和您必须跟踪的额外代码。

      正是因为这个原因,当我进行高精度计算时,我倾向于使用 NSDecimal C 结构而不是 NSDecimalNumbers。事实上,我对此进行了一些基准测试,发现使用 C 结构时性能显着提高(复制自我的回答 here):

      NSDecimal
      
      Additions per second: 3355476.75
      Subtractions per second: 3866671.27
      Multiplications per second: 3458770.51
      Divisions per second: 276242.32
      
      NSDecimalNumber
      
      Additions per second: 676901.32
      Subtractions per second: 671474.6
      Multiplications per second: 720310.63
      Divisions per second: 190249.33
      

      如您所见,NSDecimal 路径和 NSDecimalNumber 路径之间的计算速度几乎提高了五倍。 NSDecimal 和 NSDecimalNumber 计算之间的最大区别是 NSDecimalNumber 实例的内存分配。因此,您应该尽可能避免分配临时自动释放的实例。

      【讨论】:

      • 感谢您的回答。我喜欢这个答案和 Dave DeLong 使用自动释放池的建议(我希望我能同时接受)。我不认为我可以强加并询问您是否有指向正在使用的 NSDecimal 的链接,因为到目前为止我发现稀缺资源引用它。
      • 虽然可能很难解析出来,但考虑到框架的复杂性,我们最近将开源 Core Plot 框架中的所有计算都切换到了 NSDecimal。源代码可以从谷歌代码库下载:code.google.com/p/core-plot。特别是,查看 CPUtilities.m 文件,了解我们围绕 NSDecimal 构建的一些辅助函数:code.google.com/p/core-plot/source/browse/framework/Source/…
      • 感谢您的帮助。这正是我想要的。
      【解决方案3】:

      如果您担心处理太多自动释放的对象,您可以创建自己的自动释放池(请参阅memory management):

      for (count = 0; count < limit; count++)
      {
          NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
          NSString *fileContents;
          NSString *fileName;
      
          fileName = [args objectAtIndex:count];
          fileContents = [[[NSString alloc] initWithContentsOfFile:fileName] autorelease];
          // this is equivalent to using stringWithContentsOfFile:
      
          /* Process the file, creating and autoreleasing more objects. */
      
          [loopPool release];
      }
      

      【讨论】:

        【解决方案4】:

        每个获得一块内存的对象都必须放弃它。问题是什么时候。

        我尽量alloc/init/release,以便对象只在需要时才挂起。

        如果我使用autorelease,我对何时释放对象的控制较少。如果应用程序尝试访问已释放的对象,则它可能会崩溃。所以更严格的内存管理是一件好事,我认为。

        只要您保留从方法返回的自动释放对象,就应该没问题。 (除非你问别的问题,在这种情况下我提前道歉。)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-15
          • 2011-07-01
          • 2011-04-27
          • 1970-01-01
          相关资源
          最近更新 更多