问题
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?
回答1:
Yes. You should create your own autorelease pool inside the loop. This is exactly the situation that nested autorelease pools are for.
回答2:
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.
回答3:
You can get the builtin floating-point equivalents for the NSDecimalNumber
s you are using, then cast the result back into an NSDecimalNumber
at the end of the loop:
double total(0);
for (i = 0; i < 500; ++i)
{
total += [anotherDecimalNumber doubleValue];
}
resultDecimalNumber = // turn total back into an NSDecimalNumber
This technique will not only save you heaps of memory allocations inside the loop, but will also be significantly faster because you'll be using on-chip math operations instead of firing off functions.
来源:https://stackoverflow.com/questions/1336083/memory-management-with-nsdecimalnumber-how-to-avoid-memory-problems-in-tight-lo