R – Memory Management with NSDecimalNumber: How to avoid memory problems in tight loops

cocoa-touchiphonememory-managementuikit

I have a tight loop that iterates about 500 times. In every iteration, it will create a few NSDecimalNumber objects to do some arithmetics.

Example – this code snippet is in the for loop. the -decimalNumberByAdding: method creates a new NSDecimalNumber instance and autoreleases it.

resultDecimalNumber = [resultDecimalNumber decimalNumberByAdding:anotherDecimalNumber];

So let me get that right: If the loop is huge, I collect thousands of NSDecimalNumber objects which wait for the whole loop to finish and the method to return, in order to get autoreleased after long time waiting.

How could I prevent a memory overflow? I've always tried to use non-autoreleased objects, but in this case it seems I have to live with them.

Imagine this was my loop:

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

What would I have to add there? Must I create a autorelease pool inside the loop and drain it? Would that make sense?

Best Answer

Use the C struct NSDecimal. From Apple's "Number and Value Programming Topics for Cocoa":

You might consider the C interface if you don’t need to treat decimal numbers as objects—that is, if you don’t need to store them in an object-oriented collection like an instance of NSArray or NSDictionary. You might also consider the C interface if you need maximum efficiency. The C interface is faster and uses less memory than the NSDecimalNumber class.

If you need mutability, you can combine the two interfaces. Use functions from the C interface and convert their results to instances of NSDecimalNumber.

I use NSDecimal, rather than NSDecimalNumber, on the iPhone for this very reason. You get all the precision of NSDecimalNumber, with a lot less overhead.

Benchmarking the two on my Mac (MacBook Air, 2nd gen), gives these results:

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

Even ignoring the memory usage, you get a near fivefold speedup in every operation but division if you use NSDecimal and the C APIs.