Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

"Premature optimization is root of all evil" is something almost all of us have heard/read. What I am curious what kind of optimization not premature, i.e. at every stage of software development (high level design, detailed design, high level implementation, detailed implementation etc) what is extent of optimization we can consider without it crossing over to dark side.

share|improve this question
1  
    
See also: Is micro-optimisation important when coding? –  gnat May 7 '13 at 8:50
add comment

9 Answers

up vote 62 down vote accepted

When you're basing it off of experience? Not evil. "Every time we've done X, we've suffered a brutal performance hit. Let's plan on either optimizing or avoiding X entirely this time."

When it's relatively painless? Not evil. "Implementing this as either Foo or Bar will take just as much work, but in theory, Bar should be a lot more efficient. Let's Bar it."

When you're avoiding crappy algorithms that will scale terribly? Not evil. "Our tech lead says our proposed path selection algorithm runs in factorial time; I'm not sure what that means, but she suggests we commit seppuku for even considering it. Let's consider something else."

The evil comes from spending a whole lot of time an energy solving problems that you don't know actually exist. When the problems definitely exist, or when the phantom psudo-problems may be solved cheaply, the evil goes away.


Edit: Steve314 and Matthieu M. raise points in the comments that ought be considered. Basically, some varieties of "painless" optimizations simply aren't worth it either because the trivial performance upgrade they offer isn't worth the code obfuscation, they're duplicating enhancements the compiler is already performing, or both. See the comments for some nice examples of too-clever-by-half non-improvements.

share|improve this answer
11  
Occasionally, solving a phantom problem easily is still mildly evil, as it can result in harder to read, harder to maintain code. Not much harder (or it wouldn't be an easy solution), but perhaps occasionally still relevant. An example might be using a clever bitwise trick that some people won't recognise, and which the compiler will probably apply anyway if it's useful. –  Steve314 Jan 1 '11 at 12:03
12  
I agree with Steve here, sometimes the "optimization" is simply not worth it, especially because compilers are so damn good. Example ? if i is unsigned, i / 2 can be replaced by i >> 1. It is faster. But it is also more cryptic (not everyone will see the effect, even those who do may lose time). But the worst of it is that the compiler will do it anyway, so why obfuscate the source code ;) ? –  Matthieu M. Jan 1 '11 at 13:53
11  
@Larry : I didn't, so I guess it's a good example. –  Joris Meys Jan 1 '11 at 15:01
8  
In my view, optimisations, even simple ones, should also be regarded evil if they impact readabiliy/maintainabiliy of the code and are not based on actual performance measurements. –  Bart van Ingen Schenau Jan 1 '11 at 17:17
8  
+1. I've always preferred Bar to Foo anyway. Down with Foo! –  j_random_hacker Jan 7 '11 at 6:54
show 13 more comments

It's not optimisation when picking things that are hard to change eg: hardware platform.

Picking data structures is a good example - critical to meeting both functional and non-functional (performance) requirements. Not easily changed and yet it will drive everything else in your app. Your data structures change what algorithms are available etc.

share|improve this answer
add comment

The full quote defines when optimization is not premature:

A good programmer will not be lulled into complacency by such reasoning, he will be wise to look carefully at the critical code; but only after that code has been identified. [emphasis mine]

You can identify critical code in many ways: critical data structures or algorithms (e.g. used heavily or the "core" of the project) can give major optimizations, many minor optimizations are identified through profilers, and so on.

share|improve this answer
1  
Yeah... It's all well and good to shave 90% off the time a random function call takes, but maybe you'd get a bigger impact by looking at the code where your app actually spends 80% of its time and shaving off a few percent there. –  fennec Jan 14 '11 at 3:51
add comment

In my experience, at the detailed implementation phase the answer lies in profiling the code. Its important to know what needs to be faster and what is acceptably fast.

It is also important to know where exactly the performance bottleneck is - optimizing a part of the code which takes only 5% of the total time to run wont do any good.

Steps 2 and 3 describe non-premature optimization:

  1. Make it work
  2. Test. Not fast enough? Profile it.
  3. Using the data from step 2, optimize the slowest sections of the code.
share|improve this answer
    
You forgot step 0, which is: architect the application properly so that you can expect reasonable performance from the start. –  Robert Harvey Jan 6 '11 at 23:53
    
I was only speaking about the detailed implementation phase. –  Gorgi Kosev Jan 7 '11 at 1:21
    
I question step #3--very often the best answer is to figure out a different approach so you're not doing the slow bit of code in the first place. –  Loren Pechtel Jan 14 '11 at 5:25
    
Pick the right data structures. –  jasonk Mar 15 '12 at 13:25
add comment

Application code should only be as good as necessary, but library code should be as good as possible, since you never know how your library is going to be used. So when you're writing library code, it needs too be good in all aspects, be it performance, robustness, or any other category.

Also, you need to think about performance when you design your application and when you pick algorithms. If it isn't designed to be performant, no degree of hackery can make it performant afterwards and no micro-optimizations will outweigh a superior algorithm.

share|improve this answer
add comment

My general rule of thumb: if you're not sure you'll need the optimization, assume you don't. But keep it in mind for when you do need to optimize. There are some issues that you can know about up front though. This usually involves choosing good algorithms and data structures. For instance, if you need to check membership in a collection, you can be pretty sure you will need some type of set data structure.

share|improve this answer
add comment

You should always choose a "good enough" solution in all cases based on your experiences.

The optimization saying refers to writing "more complex code than 'good enough' to make it faster" before actually knowing that it is necessary, hence making the code more complex than necessary. Complexity is what makes things hard, so that isn't a good thing.

This means that you should not choose a super complex "can sort 100 Gb files by transparently swapping to disk" sorting routine when a simple sort will do, but you should also make a good choice for the simple sort in the first place. Blindly choosing Bubble Sort or "pick all entries randomly and see if they are in order. Repeat." is rarely good.

share|improve this answer
1  
+1 KISS Thorbjørn! Happy new year –  user2567 Jan 1 '11 at 14:30
4  
@Pierre, Sorry, I don't kiss on the first date of the year. You too. –  user1249 Jan 1 '11 at 16:28
    
+1 for saying refers to "more complex" ... before actually knowing –  Martin Ba Sep 29 '11 at 8:47
add comment

what kind of optimization [is] not premature

The kind that come as a result of known issues.

share|improve this answer
add comment

When you have tests to make sure you don't break anything.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.