tags:

views:

85

answers:

3

Let mFoo be an instance variable that's a property that has been synthesized, hence it has default setter and getter. I am wondering if one needs to be concerned with the performance hit of using self.mFoo vs.mFooif mFoo is accessed repeatedly in logical statements.

It seems to me that if one is absolutely certain that a method does not have a local variable mFoo declared, and one is doing several logical comparison with mFoo within a method, and the method is called a lot, that it makes sense not to access mFoo through its accessor method but directly.

For example:

NSMutableArray *mFoo;
@property(nonatomic, retain) NSMutableArray *mFoo;
@synthesize mFoo;

-(void)someMethod {
    Bar* b;
    for (int i=0; i<10000; i++) {
        b = [self.mFoo objectAtIndex:i];   // <<<<<<<<<<<<<<<<
        if (b.something == 123) { // do something };
    }
 }
A: 

For every access to self.mFoo, about one C function would have to be called if fast Objective C message dispatch is enabled (unless the compiler optimizes that call away). So the performance hit won't be noticeable most of the time. In the example you mentioned, you should use fast enumeration like

for (Bar *b in self.mFoo) {
    // do whatever you wish to here
}

, which will lead to self.mFoo being accessed just once and is faster in general (e.g. if your array is really a list).

MrMage
An ahead of time compiler can't optimize it a way. Because of how message dispatch and introspection work in Objective C it is effectively impossible to know if it is safe to inline a method unless the compiler has complete information about all linkage units (and even then it may be difficult). Since the compiler doesn't ever have that information (Mac OS X supports loadable modules, and most of us don't have the source code to Foundation). In the future it may be possible to do some sort of monomorphic dispatch inlining if you are using ObjC in a JIT'ted environment.
Louis Gerbarg
`for( ... in ...)` is a great suggestion. However, there is no "enabling or disabling" objc message dispatch in this case. Nor any optimization opportunities on the compiler's part.
bbum
Louis: You are right, I didn't think of that.bbum: There is a fast Objective C message dispatch option which makes these calls quite fast. But you are right, messages will always be sent.
MrMage
The fast message dispatch option isn't for all platforms and it works by avoiding a dereference through DYLD by moving the objc_msgSend* functions to bit of shared memory in a fixed address across all processes.
bbum
+2  A: 

If you're accessing the property from another class, you should always use the accessor method or dot notation. That's just basic OO hygiene. In the unlikely case that you discover that this causes a bottleneck in a loop or something, you can think about some tailor-made solution at that point.

If you're accessing the variable from within the class, I think it's ok to access the ivar directly rather than through the property if you are getting the value. However, if you are setting the value you should always use the propery, both in order to avoid memory leaks and because the setter might have logic that should be executed.

So:

CGSize sz = [self size]; //ok
CGSize sz = self.size; //ok
CGSize sz = _size; //ok, but be careful

[self setSize:sz]; //ok
self.size = sz, //ok
_size = sz; // DON'T EVER DO THIS!

However, if you have an ivar that doesn't even have a property associated with it, you should needless to say access it directly (you don't have much choice...). Personally, I usually declare properties for all ivars except some flags or counters with non-object types, but many people don't.

Felixyz
+1 for the comment on special caution necessary for setters.
MrMage
+3  A: 
bbum
@bbum "Never grab values directly..." Do you follow this strictly even from within a class? Do you never let a class get *its own* ivar values if they have properties associated with them?
Felixyz
Generally, yes. If there is key-value observation in play, then going through the setter/getters will fire the observations.
bbum
@Apple Please use self. in your sample code and Xcode templates. From the Xcode template created project: [window addSubview:[navigationController view]]; [window makeKeyAndVisible];
zaph