Back in the seventies, Knuth wrote the above quote in his paper “Structured Programming with go to Statement” at times when computational power was slower and expensive than nowadays. Nevertheless, it doesn’t mean you shouldn’t take it in your consideration. Note that the quote doesn't stand for itself, and to get its true meaning, you should read the paragraph that follows this famous saying:
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.
To me, what it really means, there are obvious optimizations (like not doing string concatenation inside a loop). Still, anything that isn’t a trivially clear optimization should be avoided until it can be measured. Failed to do so can introduce unexpected bugs and can result in high efforts to overcome them.
That being said, measurements can lie. Focusing on hot-paths and optimizing them might cause you to miss that it is a symptom of poorly designed code. There is a simple solution: be sure to design first. Thus, a more holistic approach will be finding those places that don’t correlate with your design and adjust them accordingly.
Note that until you‘ve written code that you can measure, you’ll have to make some performance decisions before anything exists. 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.
Furthermore, I saw cases that premature optimization was used (or abused) as an argument for not designing your entire application architecture to run fast in general, scale, and be easily optimizable—basically, an excuse not to optimize code at all. Don’t be confused. Designing a solution is your engineering responsibility.
How early to optimize and how much to worry about performance depends on the task. When writing a script that runs a few times and only by you, I would worry less about performance. But if you work on a service with many users and will be used in different ways — be sure to optimize to cover all the diverse use cases efficiently.
However, a balance must be struck between performance and readability, maintainability, elegance, extensibility, and so on.
To Wrap up
Slow performance can’t be blamed on the language or tool or CPU or memory. It’s a delicate balance of so many things, which is why it’s nearly impossible to optimize early.
The developer has to balance between design and optimization. To my understanding, he should design first, code, and profile it to see which parts should be optimized, and do it iteratively. Here’s a great example.
A simple and elegant design is often easier to optimize at these earlier stages, and profiling may reveal unexpected performance problems that would not have been addressed by premature optimization.