views:

351

answers:

4

I have a requirement to create some NSDecimalNumber objects objects as part of my application (as I require the precision of calculation they offer) but I note that in calculations they return NSDecimalNumber objects which are, presumably, autoreleased.

My question is really whether this is potentially problematic in an iPhone application where I may carry out lots of calculations.

The question is not just relating to NSDecimalNumber specifically but to the sometimes unavoidable creation of autoreleased objects in the course of developing an iPhone application.

Any detailed answers on this point would be gratefully received.

A: 

Every object that is given a chunk of memory will have to relinquish it. The question is when.

I try to alloc/init/release when I can, so that objects only hang around as long as they are needed.

If I use autorelease I have less control over when the object is released. If the application tries to access a released object then it can crash. So tighter memory management is a good thing, I think.

So long as you retain autoreleased objects returned from a method, you should be okay. (Unless you're asking about something else, in which case I apologize in advance.)

Alex Reynolds
+6  A: 

Remember, you can create your own NSAutoreleasePool objects.

For example:

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];
}

If you do that, you'll never have more than 1000 of those strings in memory at a time.

Dave DeLong
+3  A: 

If you are worried about handling too many autoreleased objects you can create your own autorelease pool (see 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];
}
stefanB
+5  A: 

Yes, creating lots of autoreleased instances on the iPhone can create memory problems, particularly in a tight loop, which is why I tend to avoid them when I can. You can create your own autorelease pools to manage this, but they also add some performance overhead and additional code that you have to keep track of.

It is for this reason that when I do high-precision calculations, I tend to use the NSDecimal C struct instead of NSDecimalNumbers. In fact, I performed some benchmarks on this and found a significant performance increase when going with the C struct (copied from my answer 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

As you can see, there is almost a fivefold increase in calculation speed between the NSDecimal paths and NSDecimalNumber ones. The biggest difference between the NSDecimal and NSDecimalNumber calculations was the memory allocation of the NSDecimalNumber instances. Therefore, you should avoid allocating temporary autoreleased instances wherever you can.

Brad Larson
Thank you for your answer. I like this answer and the suggestion by Dave DeLong of using the autorelease pools (I wish that I could accept both). I don't suppose that I could impose and ask if you have a link to the NSDecimal being used as I have found scarce resources referring to it so far.
Urizen
While it might be hard to parse out, given the complexity of the framework, we recently switched all of the calculations in the open source Core Plot framework to NSDecimal. The source code can be downloaded from the Google Code repository: http://code.google.com/p/core-plot/ . In particular, look at the CPUtilities.m file for some helper functions we've built around NSDecimal: http://code.google.com/p/core-plot/source/browse/framework/Source/CPUtilities.m
Brad Larson
Thank you for the help. This is exactly what I was looking for.
Urizen