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.

A colleague of mine today committed a class called ThreadLocalFormat, which basically moved instances of Java Format classes into a thread local, since they are not thread safe and "relatively expensive" to create. I wrote a quick test and calculated that I could create 200,000 instances a second, asked him was he creating that many, to which he answered "nowhere near that many". He's a great programmer and everyone on the team is highly skilled so we have no problem understanding the resulting code, but it was clearly a case of optimizing where there is no real need. He backed the code out at my request. What do you think? Is this a case of "premature optimization" and how bad is it really?

share|improve this question

migrated from stackoverflow.com May 29 '11 at 8:37

This question came from our site for professional and enthusiast programmers.

9  
I think you need to distinguish between premature optimization, and unnecessary optimization. Premature to me suggests 'too early in the life cycle' wheras unncessary suggests 'does not add significant value'. IMO, requirement for late optimization implies shoddy design. –  Shane MacLaughlin Oct 17 '08 at 8:53
46  
Yes, but evil is a polynomial and has many roots, some of them are complex. –  dan_waterworth May 29 '11 at 12:31
3  
Joe Duffy blogged about this in 2010: The Premature Optimization Is Evil Myth –  Laoujin Jan 9 '13 at 10:01
    
duplicate of: When is optimization not premature and therefore not evil? –  gnat Apr 17 '13 at 14:51
2  
You should consider, that Knuth wrote this 1974. In the seventies it was not that easy to write slow programs as it is nowadays. He wrote with Pascal in mind and not with Java or PHP. –  ceving Oct 2 '13 at 13:51

15 Answers 15

up vote 133 down vote accepted

It's important to keep in mind the full quote:

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%.

What this means is that, in the absence of measured performance issues you shouldn't optimize becuase you think you will get a performance gain. There are obvious optimizations (like not doing string concatenation inside a tight loop) but anything that isn't a trivially clear optimization should be avoided until it can be measured.

The biggest problems with "premature optimization" are that it can introduce unexpected bugs and can be a huge time waster.

share|improve this answer
19  
++ for the full(er) quote. –  Ed Guiness Oct 17 '08 at 9:42
1  
Second that on the complete quote. Wonder how he measured the 97% and 3%? ;) –  Shane MacLaughlin Oct 17 '08 at 10:30
5  
Being from Donald Knuth, I wouldn't be surprized if he had some evidence to back it up. BTW, Src: Structured Programming with go to Statements, ACM Journal Computing Surveys, Vol 6, No. 4, Dec. 1974. p.268. citeseerx.ist.psu.edu/viewdoc/… –  mctylr Mar 1 '10 at 17:57
10  
... 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 (rest of fuller quotation) –  mctylr Mar 1 '10 at 17:59
1  
@mctylr : highlight, in bold, upper case and highlighter "CRITICAL" and "HAS BEEN IDENTIFIED"- far too many of us forget those most important words. –  mattnz May 1 '12 at 22:46

Id's say premature micro optimizations are the root of all evil, because micro optimizations out context. almost never behave the way they are expected.

What are some good early optimizations in the order of importance:

  • Architectural optimizations (application structure, the way it's componentized and layered)
  • Data flow optimizations (inside and outside of application)

Some mid development cycle optimizations:

  • Data structures, introduce new data structures that have better performance or lower overhead if necessary
  • Algorithms (now its a good time to start deciding between quicksort3 and heapsort ;-) )

Some end development cycle optimizations

  • Finding code hotpots (tight loops, that should be optimized)
  • Profiling based optimizations of computational parts of the code
  • Micro optimizations can be done now as they are done in the context of the application and their impact can be measured correctly.

So to answer your question :-) :

Not all early optimizations are evil, micro optimizations are evil if done at the wrong time in the development life cycle, as they can negatively affect architecture, can negatively affect initial productivity, can be irrelevant performance wise or even have a detrimental effect at the end of development due to different environment conditions.

If performance is of concern (and always should be) always think big. Performance is a bigger picture and not about things like: should I use int or long?. Go for Top Down when working with performance instead of Bottom Up.

share|improve this answer
1  
Yes, That hits it right on the head! –  BCS Dec 19 '08 at 21:01

optimization without first measuring is almost always premature.

I believe that's true in this case, and true in the general case as well.

share|improve this answer
    
Here Here! Unconsidered optimization makes code un-maintainable and is often the cause of performance problems. e.g. You multi-thread a program because you imagine it might help performance, but, the real solution would have been multiple processes which are now too complex to implement. –  James Anderson May 2 '12 at 5:01
    
unless it's documented. –  nawfal Jul 2 at 13:18

Optimization is "evil" if it causes:

  • less clear code
  • significantly more code
  • less secure code
  • wasted programmer time

In your case, it seems like a little programmer time was already spent, the code was not too complex (a guess from your comment that everyone on the team would be able to understand), and the code is a bit more future proof (being thread safe now, if I understood your description). Sounds like only a little evil. :)

share|improve this answer
2  
Only if the cost, it terms of your bullet points, is greater than the amortized value delivered. Often complexity introduces value, and in these cases one can encapsulate it such that it passes your criteria. It also gets reused and continues to provide more value. –  Shane MacLaughlin Oct 17 '08 at 10:36
    
Those first two points are the main ones to me, with the fourth point being a negative consequence of doing premature optimization. In particular, it is a red flag whenever I see someone re-implementing features from a standard library. Like, I once saw someone implement custom routines for string manipulation because he was concerned that the built-in commands were too slow. –  jhocking May 29 '11 at 12:47
    
Making code thread safe is not optimization. –  mattnz May 1 '12 at 22:47

Personally, as covered in a previous thread, I don't believe early optimization is bad in situations where you know you will hit performance issues. For example, I write surface modelling and analysis software, where I regularly deal with tens of millions of entities. Planning for optimal performance at design stage is far superior than late optimization of a weak design.

Another thing to consider is how your application will scale in the future. If you consider that your code will have a long life, optimizing performance at design stage is also a good idea.

In my experience, late optimization provides meagre rewards at a high price. Optimizing at design stage, through algorithm selection and tweaking, is way better. Depending on a profiler to understand how your code works is not a great way of getting high performance code, you should know this beforehand.

share|improve this answer
    
This is certainly correct. I guess that premature optimization is when code is made more complex / hard to understand for unclear benefits, in a way that has only local impact (design has global impact). –  Paul de Vrieze Oct 17 '08 at 10:12
2  
It's all about definitions. I take optimization as designing and writing code to perform in an optimal manner. Most here appear to treat it as hacking about with the code once they have found it is not fast or efficient enough. I spend a lot of time optimizing, usually during design. –  Shane MacLaughlin Oct 17 '08 at 10:27
2  
Optimize the design at the start, Optimize the code at the end. –  BCS Dec 19 '08 at 20:58
    
You are quite correct in your case, however for most programmers, they believe they will hit performance issues, but in reality they never will. Many worry about performance when dealing with 1000 of entities, when a basic test on the data would show that performance is fine until they hit 1000000 entities. –  Toby Allen Jan 26 '13 at 15:32

I'm surprised that this question is 5 years old, and yet nobody has posted more of what Knuth had to say than a couple of sentences. The couple of paragraphs surrounding the famous quote explain it quite well. The paper that is being quoted is called "Structured Programming with go to Statements", and while it's nearly 40 years old, is about a controversy and a software movement that both no longer exist, and has examples in programming languages that many people have never heard of, a surprisingly large amount of what it said still applies.

Here's a larger quote (from page 8 of the pdf, page 268 in the original):

The improvement in speed from Example 2 to Example 2a is only about 12%, and many people would pronounce that insignificant. The conventional wisdom shared by many of today's software engineers calls for ignoring efficiency in the small; but I believe this is simply an overreaction to the abuses they see being practiced by penny-wise-and-pound-foolish programmers, who can't debug or maintain their "optimized" programs. In established engineering disciplines a 12% improvement, easily obtained, is never considered marginal; and I believe the same viewpoint should prevail in software engineering. Of course I wouldn't bother making such optimizations on a one-shot job, but when it's a question of preparing quality programs, I don't want to restrict myself to tools that deny me such efficiencies.

There is no doubt that the grail of efficiency leads to abuse. Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs, and these attempts at efficiency actually have a strong negative impact when debugging and maintenance are considered. We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.

Yet we should not pass up our opportunities in that critical 3%. 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. It is often a mistake to make a priori judgments about what parts of a program are really critical, since the universal experience of programmers who have been using measurement tools has been that their intuitive guesses fail.

Another good bit from the previous page:

My own programming style has of course changed during the last decade, according to the trends of the times (e.g., I'm not quite so tricky anymore, and I use fewer go to's), but the major change in my style has been due to this inner loop phenomenon. I now look with an extremely jaundiced eye at every operation in a critical inner loop, seeking to modify my program and data structure (as in the change from Example 1 to Example 2) so that some of the operations can be eliminated. The reasons for this approach are that: a) it doesn't take long, since the inner loop is short; b) the payoff is real; and c) I can then afford to be less efficient in the other parts of my programs, which therefore are more readable and more easily written and debugged.

share|improve this answer

I've often seen this quote used to justify obviously bad code or code that, while its performance has not been measured, could probably be made faster quite easily, without increasing code size or compromising its readability.

In general, I do think early micro-optimizations may be a bad idea. However, macro-optimizations (things like choosing an O(log N) algorithm instead of O(N^2)) are often worthwhile and should be done early, since it may be wasteful to write a O(N^2) algorithm and then throw it away completely in favor of a O(log N) approach.

Note the words may be: if the O(N^2) algorithm is simple and easy to write, you can throw it away later without much guilt if it turns out to be too slow. But if both algorithms are similarly complex, or if the expected workload is so large that you already know you'll need the faster one, then optimizing early is a sound engineering decision that will reduce your total workload in the long run.

Thus, in general, I think the right approach is to find out what your options are before you start writing code, and consciously choose the best algorithm for your situation. Most importantly, the phrase "premature optimization is the root of all evil" is no excuse for ignorance. Career developers should have a general idea of how much common operations cost; they should know, for example,

  • that strings cost more than numbers
  • that dynamic languages are much slower than statically-typed languages
  • the advantages of array/vector lists over linked lists, and vice versa
  • when to use a hashtable, when to use a sorted map, and when to use a heap
  • that (if they work with mobile devices) "double" and "int" have similar performance on desktops (FP may even be faster) but "double" may be a hundred times slower on low-end mobile devices without FPUs;
  • that transferring data over the internet is slower than HDD access, HDDs are vastly slower than RAM, RAM is much slower than L1 cache and registers, and internet operations may block indefinitely (and fail at any time).

And developers should be familiar with a toolbox of data structures and algorithms so that they can easily use the right tools for the job.

Having plenty of knowledge and a personal toolbox enables you to optimize almost effortlessly. Putting a lot of effort into an optimization that might be unnecessary is evil (and I admit to falling into that trap more than once). But when optimization is as easy as picking a set/hashtable instead of an array, or storing a list of numbers in double[] instead of string[], then why not? I might be disagreeing with Knuth here, I'm not sure, but I think he was talking about low-level optimization whereas I am talking about high-level optimization.

Remember, that quote is originally from 1974. In 1974 computers were slow and computing power was expensive, which gave some developers a tendency to overoptimize, line-by-line. I think that's what Knuth was pushing against. He wasn't saying "don't worry about performance at all", because in 1974 that would just be crazy talk. Knuth was explaining how to optimize; in short, one should focus only on the bottlenecks, and before you do that you must perform measurements to find the bottlenecks.

Note that you can't find the bottlenecks until you have written a program to measure, which means that some performance decisions must be made before anything exists to measure. Sometimes these decisions are difficult to change if you get them wrong. For this reason, it's good to have a general idea of what things cost so you can make reasonable decisions when no hard data is available.

How early to optimize, and how much to worry about performance depend on the job. When writing scripts that you'll only run a few times, worrying about performance at all is usually a complete waste of time. But if you work for Microsoft or Oracle and you're working on a library that thousands of other developers are going to use in thousands of different ways, it may pay to optimize the hell out of it, so that you can cover all the diverse use cases efficiently. Even so, the need for performance must always be balanced against the need for readability, maintainability, elegance, extensibility, and so on.

share|improve this answer
1  
Amen. Premature optimization is thrown around far too liberally these days by people who try to justify using the wrong tool for the job. If you know the right tool for the job ahead of time, then there is no excuse for not using it. –  crush Jan 23 at 14:42

There are two problems with PO: firstly, the development time being used for non-essential work, which could be used writing more features or fixing more bugs, and secondly, the false sense of security that the code is running efficiently. PO often involves optimising code that isn't going to be the bottle-neck, while not noticing the code that will. The "premature" bit means that the optimisation is done before a problem is identified using proper measurements.

So basically, yes, this sounds like premature optimisation, but I wouldn't necessarily back it out unless it introduces bugs - after all, it's been optimised now(!)

share|improve this answer
    
You mean to say "writing more tests" instead of "writing more features", right? :) –  Greg Hewgill Oct 17 '08 at 8:42
    
more features entails more tests :) –  workmad3 Oct 17 '08 at 8:51
    
Er, yes! That's exactly what I meant... –  harriyott Oct 17 '08 at 9:40
2  
The code introduces further complexity, and will likely not be universally used. Backing it (and similar things) out keeps the code clean. –  Paul de Vrieze Oct 17 '08 at 10:07

I believe it's what Mike Cohn calls 'gold-plating' the code - i.e. spending time on things which could be nice but are not necessary.

He advised against it.

P.S. 'Gold-plating' could be bells-and-whistles kind of functionality spec-wise. When you look at the code it takes form of unnecessary optimisation, 'future-proofed' classes etc.

share|improve this answer
2  
I think "gold-plating" is different than optimizations. Optimizations are generally all about trying to get the most performance while "gold-plating" is about adding the "bells and whistles" (all the extra functionality) that isn't critical to the product but looks/feels cool to do. –  Scott Dorman Oct 17 '08 at 9:16

Since there is no problem understanding the code, then this case could be considered as an exception.

But in general optimization leads to less readable and less understandable code and should be applied only when necessary. A simple example - if you know that you have to sort only a couple of elements - then use BubbleSort. But if you suspect that the elements could increase and you don't know how much, then optimizing with QuickSort (for example) is not evil, but a must. And this should be considered during the design of the program.

share|improve this answer
1  
Don't agree. I'd say never use a bubble sort. Quicksort has become a defacto standard and is well understood, and is as easy to implement as a bubble sort in all scenarios. The lowest common denominator is not that low any more ;) –  Shane MacLaughlin Oct 17 '08 at 8:47
1  
For really small numbers of items, the recursion required for quicksort can make it slower than a decent bubblesort though... not to mention that a bubblesort is quicker in the worst-case scenario of quicksort (namely quicksorting a sorted list) –  workmad3 Oct 17 '08 at 8:53
    
yeah, but that's just an example how to select algorithms for different needs ;) –  m_pGladiator Oct 17 '08 at 8:54
    
True, but I would have quicksort as my default sort. If I thought bubblesort would improve performance, this would be an optimization, not the other way around. I choose quicksort as my default because it is well understood and generally better. –  Shane MacLaughlin Oct 17 '08 at 9:15
2  
My idea of a default sort is whatever the library gives me (qsort(), .sort(), (sort ...), whatever). –  David Thornley Dec 19 '08 at 21:25

I've found that the problem with premature optimization mostly happens when re-writing existing code to be faster. I can see how it could be a problem to write some convoluted optimization in the first place, but mostly I see premature optimization rearing its ugly head in fixing what ain't (known to be) broke.

And the worst example of this is whenever I see someone re-implementing features from a standard library. That is a major red flag. Like, I once saw someone implement custom routines for string manipulation because he was concerned that the built-in commands were too slow.

This results in code that is harder to understand (bad) and burning a lot of time on work that probably isn't useful (bad).

share|improve this answer

Premature optimization is not the root of ALL evil, that's for sure. There are however drawbacks to it:

    - you invest more time durring development
    - you invest more time testing it
    - you invest more time fixing bugs that otherwise wouldn't be there

Instead of premature optimization, one could do early visibility tests, to see if there's an actual need for better optimization.

share|improve this answer

The answer is: it depends. I'll argue that efficiency is a big deal for certain types of work, such as complex database queries. In many other cases the computer is spending most of its time waiting for user input so optimising most code is at best a waste of effort and at worst counterproductive.

In some cases you can design for efficiency or performance (perceived or real) - selecting an appropriate algorithm or designing a user interface so certain expensive operations happen in the background for example. In many cases, profiling or other operations to determine hotspots will get you a 10/90 benefit.

One example of this I can describe is the data model I once did for a court case management system which had about 560 tables in it. It started out normalised ('beautifully normalised' as the consultant from a certain big-5 firm put it) and we only had to put four items of denormalised data in it:

  • One materialised view to support a search screen

  • One trigger-maintained table to support another search screen that could not be done with a materialised view.

  • One denormalised reporting table (this only existed because we had to take on some throughput reports when a data warehouse project got canned)

  • One trigger-maintained table for an interface that had to search for the most recent of quite a large number of disparate events within the system.

This was (at the time) the largest J2EE project in Australasia - well over 100 years of developer time - and it had 4 denormalised items in the database schema, one of which didn't really belong there at all.

share|improve this answer

I suppose it depends on how you define "premature". Making low-level functionality quick when you're writing is not inherently evil. I think that's a misunderstanding of the quote. Sometimes I think that quote could do with some more qualification. I'd echo m_pGladiator's comments about readability though.

share|improve this answer

In fact I learned that premature non-optimization is more often the root of all evil. When people write software it will initially have problems, like instability, limited features, bad usability and bad performance. All of these usually get fixed, when the software matures. All of these, except performance. Noone seems to care about performance. The reason is simple: if a software crashes, someone will fix the bug and that's it, if a feature is missing, someone will implement it and done, if the software has bad performance it is in many cases not due to missing microoptimization, but due to bad design and noone is going to touch the design of the software. EVER. Look at Bochs. It's slow as hell. Will it ever get faster? Maybe, but only in the range of a few percent. It will never get performance comparable to virtualization software like VMWare or VBox or even QEMU. Because it's slow by design! If the problem of a software is that it is slow, then because it is VERY slow and this can only be fixed by improving the performance by a multitude. +10% will simply not make a slow software fast. And you will usually not get more than 10% by later optimizations. So if performance is ANY important for your software, you should take that into account from the beginning on, when designing it, instead of thinking "oh yes, it's slow, but we can improve that later". Because you can't! I know that does not really fit to your specific case, but it answers the general question "Is premature optimization really the root of all evil?" - with a clear NO. Every optimization, like any feature, etc. has to be designed carefully and implemented carefully. And that includes a proper evaluation of cost and benefit. Do not optimize an algorithm to save a few cycles here and there, when it doesn't create a measurable performance gain. Just as an example: you can improve a function's performance by inlining it, possibly saving a handful of cycles, but at the same time you probably increase the size of your executable, increasing the chances of TLB and cache misses costing thousands of cycles or even paging operations, which will kill performance entirely. If you don't understand these things, your "optimization" can turn out bad. Stupid optimization is more evil than "premature" optimzation, yet both are still better than premature non-optimization.

share|improve this answer
1  
Wow, what a wall of text. Could you please add some line breaks at least? –  Martijn Pieters Oct 27 '13 at 0:58

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.