【问题标题】:Memory Management with NSDecimalNumber: How to avoid memory problems in tight loops?使用 NSDecimalNumber 进行内存管理:如何避免紧密循环中的内存问题?
【发布时间】:2009-08-26 16:46:26
【问题描述】:

我有一个迭代大约 500 次的紧密循环。在每次迭代中,它都会创建一些 NSDecimalNumber 对象来做一些算术运算。

示例 - 此代码 sn-p 在 for 循环中。 -decimalNumberByAdding: 方法创建一个新的 NSDecimalNumber 实例并自动释放它。

resultDecimalNumber = [resultDecimalNumber decimalNumberByAdding:anotherDecimalNumber];

所以让我做对了:如果循环很大,我会收集数千个 NSDecimalNumber 对象,这些对象等待整个循环完成并返回方法,以便在长时间等待后自动释放。

如何防止内存溢出?我一直尝试使用非自动释放的对象,但在这种情况下,我似乎不得不忍受它们。

想象一下这是我的循环:

for(i=0, i<500, i++) {
    resultDecimalNumber = [resultDecimalNumber decimalNumberByAdding:anotherDecimalNumber];
}

我必须在那里添加什么?我必须在循环内创建一个自动释放池并将其排空吗?这有意义吗?

【问题讨论】:

    标签: iphone cocoa-touch memory-management uikit


    【解决方案1】:

    使用 C 结构 NSDecimal。来自 Apple 的"Number and Value Programming Topics for Cocoa"

    你可以考虑 C 接口,如果 你不需要处理小数 数字作为对象——也就是说,如果你 不需要将它们存储在 像一个面向对象的集合 NSArray 或 NSDictionary 的实例。 你也可以考虑 C 如果你需要最大的接口 效率。 C接口更快 并且使用的内存比 NSDecimalNumber 类。

    如果你需要可变性,你可以 结合两个接口。采用 C接口的函数和 将他们的结果转换为 NSDecimalNumber。

    出于这个原因,我在 iPhone 上使用 NSDecimal,而不是 NSDecimalNumber。您可以获得 NSDecimalNumber 的所有精度,而且开销要少得多。

    在我的 Mac(MacBook Air,第二代)上对两者进行基准测试,得出以下结果:

    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 和 C API,您在除除法之外的每个操作中都会获得近五倍的加速。

    【讨论】:

    • 谢谢伙计。会看看那个。
    • +1 非常好的基准测试。我知道 C 接口,但不知道你会看到什么样的速度。
    【解决方案2】:

    是的。您应该在循环内创建自己的自动释放池。这正是嵌套自动释放池的用途。

    【讨论】:

    • 虽然 Brad Larson 为问题本身提供了更好的解决方案,但 Rob Napier 的回答对问题本身来说是正确的,所以我决定检查一下。致所有人:有关使用 NSDecimalNumber 的更好解决方案,请参阅 Brad 的帖子。
    【解决方案3】:

    您可以获得您正在使用的NSDecimalNumbers 的内置浮点等效项,然后在循环结束时将结果转换回NSDecimalNumber

    double total(0);
    
    for (i = 0; i < 500; ++i)
    {
        total += [anotherDecimalNumber doubleValue];
    }
    
    resultDecimalNumber = // turn total back into an NSDecimalNumber
    

    这种技术不仅可以为您节省循环内的大量内存分配,而且还可以显着加快速度,因为您将使用片上数学运算而不是触发函数。

    【讨论】:

    • 如果您想保持精度并避免浮点错误,这是不可取的。如果这是您要采用的方法,您最好不要使用 NSDecimalNumber,而是使用双精度值。
    • 同意。首先打破 NSDecimals 的唯一原因是双重数学不适合您的问题。如果有的话,在少数情况下可能会采用另一种方式(使用 NSDecimals 进行高精度数学运算并在最后返回一个双精度数),但我无法想象使用上述方法。
    猜你喜欢
    • 2011-03-20
    • 1970-01-01
    • 2011-04-24
    • 2019-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多