+4  A: 

First rule of optimization: never optimize without benchmarks verifying what needs optimizing. Otherwise you're suffering from 'premature optimization', and a lot of (potentially) wasted effort.

Now, if you know that something takes 2s to run,and you're running in 4 times when you could be running it once - that would be justifiable. but it sounds like you're not sure in this case, so the answer is "benchmark it"

cyberconte
Although this is absolutely true (and one of my favorite rules), correcting wrong programming is not premature optimization. Calling an unnecessary operation, unnecessary inner loops, random lookups in a linked list or an insertion sort into an array list would all be examples of bad code, not unoptimized code.
Bill K
It may be bad code, but its not incorrect code, and thus i contend everything you mentioned is by definition an optimization.
cyberconte
+3  A: 

The short answer: none. At least not right now.

I don't think the compiler will recognize that you're running [results count] twice, BUT that shouldn't matter. The usual quote on this subject is that "premature optimization is the root of all evil". Write your code however you want to; think about readability first. Then, after you've finished, and you've actually noticed that your code is slow, then go back and find optimizations if necessary.

So the rule is: write sensible, readable code, and optimize afterwards if problems are discovered.

andyvn22
+1  A: 

The compiler will not pick up the fact that you already ran it.

Fixing this is not an optimization, it's simply programming correctly. There are a few things that you just have to be aware of that go beyond optimization.. most of them involve unnecessary looping of one sort or another.

Would it be really hard to just pull it out into a separate variable?

NSArray *results = [context executeFetchRequest:request error:&error];
NSUInteger count=[results count];
NSMutableArray *firstArray  = [[[NSMutableArray alloc] initWithCapacity:count] autorelease];
NSMutableArray *secondArray = [[[NSMutableArray alloc] initWithCapacity:count] autorelease];

Which is absolutely no less clear (possibly more clear).

Anyway, executing unbounded unnecessary loops need to be avoided, it's not optimization, it's just wrong.

And please don't think I don't understand the cons of premature optimization, I've ranted about it repeatedly in replies to other questions...

As for your other question, never "optimize" without a test or spec showing that your code is running too slow, but DON'T code poorly. Always be aware of inner loops and things that might cause inner loops--these are the most critical.

An insertion sort into an array list causes an inner loop, an insertion sort into a linked list does not...

iterating over a linked list causes an inner loop (assuming you are using the loop index to retrieve the "Next" value instead of holding onto the node and referencing .next which would be fine), iterating over an array list does not.

Comparing two lists often requires an inner loop and it's often worth looking over your data to try to figure out a way that an inner loop is not required (for instance, if they are both sorted you can code such that you won't get an inner loop.

Bill K
Some (including myself) would argue that is less readable, and the speed benefit you'd get is probably negligible. Personally, I'd much prefer to see [results count] than have to keep track of a new variable, i, just to remove a single 'count' message. But that's personal style; some say my method nests too many square brackets to be readable. My point, however, is that readability, one way or the other based on preference, should probably still trump this "correct programming".
andyvn22
As for readability--it's close. You're not tracking a new variable because it's only used in that one spot. If you wanted to, you can even scope it, but if you keep your functions small, it should already be reasonably scoped. Lines that do multiple things are often fun to write and easy to understand as you write it because they can encapsulate a single concept, but the multi-line equivalent is always easier to read when you are seeing it for the first time. Anyway, the "Correct Programming" part is about not invoking unnecessary code repeatedly, not my particular solution.
Bill K
`int` is signed and may be too short. The correct type is `NSUInteger`.
Peter Hosey
I guess that makes sense. I suppose that maps to unsigned int via a macro (which then should work). Not knowing O-c much made me wonder what might be under the covers. I didn't know they made macros for all the variables, I thought they would only do the ones you'd have to allocate and release... I'll update.
Bill K
Rather than supposing, find out! Command-double-click the word NSUInteger in Xcode, and you’ll find it’s typedefed to either unsigned int or unsigned long depending on target architecture. (Remember, int is 32 bits in 64-bit Mac environments, so int really could be too short.)In purely practical terms, it’s the same size as unsigned long on all targets it’s defined on, but using long for 32-bit would have changed the @encode() strings for existing types and methods, which could have caused compatibility problems.
Ahruman
+3  A: 

To answer the actual question: no, an Objective-C compiler cannot optimize away method sends, ever. (Well, actually, there’s one possible case: if it knows for certain that the receiver is nil.)

There is no way for a class to provide guarantees about method behaviour (in particular, you can’t use gcc’s __attribute__((const)) and such with a method), and there is no way for the compiler to tell what method implementation will be called because of Objective-C’s dynamic nature. For example, results could actually be a proxy object which forwards the count method to a random object each time it’s called. There’s no particular reason for Core Data to do that, but the compiler doesn’t know that.

All that aside, the cost of calling -[NSArray count] is trivial, and there’s absolutely no way that particular method will be a bottleneck in anything but extremely contrived code. The habit of avoiding double calls can reasonably be argued to be worthwhile, but actually worrying about the cost or going back to “correct” it for performance reasons would be a waste of time, quite likely more time than your program will spend calling -[NSArray count] throughout its useful lifetime.

Ahruman
That sounds like an argument for doing it; the time spent making the change will be less than the time spent worrying over whether it ought to be done :-)
Graham Lee
Ah, but the time spent debating it will vastly out-cost the cost of asking the question in the first place or the cost of (not) doing the optimization ...
AlBlue
Thanks for the tidbit about the Objective-C compiler and method sends - hadn't known that before. +1
Tim