You’ve probably heard someone say “premature optimization is the root of all evil” in a code review.
But the story changes when you read the original. Donald Knuth definitely did not mean “never optimize.”
Here’s the conclusion first: Knuth said to “forget about the 97% of the small efficiencies, but not pass up our opportunities in that critical 3%.” The commonly quoted half-sentence cuts off everything that follows.
Today, let’s look at the quote’s real context and when you should optimize code.
This is what the original actually said
The quote comes from a 1974 paper by Donald Knuth titled “Structured Programming with go to Statements,” published in ACM Computing Surveys.
Here is the original wording.
“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%.”
See the difference? The sentence we know is just the middle fragment.
It begins with “forget the 97%” and ends with “don’t miss the 3%.” These three sentences form a single set.
Knuth wasn’t saying not to optimize. He was saying to choose where to focus your effort.
“Forget the 97% and focus on the 3%”—that’s the point
Knuth made another related point in the same paper.
Programmers waste enormous amounts of time worrying about the speed of parts of a program that are not important.
Optimizations made in advance can instead make debugging and maintenance more difficult.
The problem is not optimization itself, but its timing and location. Trouble starts when you change code arbitrarily without knowing where the bottleneck is.
It doesn’t mean “never optimize”; it means “don’t optimize arbitrarily without evidence.”
So when should you optimize?
It’s the most common question. The answer is simple: do it after measuring.
You find Knuth’s critical 3% through measurement, not intuition. Run a profiler, find what is actually consuming time, and optimize that part.
With Swift, you can start by checking the bottleneck like this.
// Measure which code is actually consuming time
let clock = ContinuousClock()
let elapsed = clock.measure {
slowFunction()
}
print(elapsed) // The section taking the most time is the one '3%'
Measurements often prove our expectations wrong. The place you thought would be slow is fine, while an overlooked loop is consuming the whole runtime.
This distinction makes premature and justified optimization easier to understand.
| Category | Premature optimization | Justified optimization |
|---|---|---|
| Timing | Before measuring, by intuition | After measuring, using data |
| Target | Any noticeable area | The 3% confirmed as the bottleneck |
| Result | Only more complex code | Actual performance improvement |
One more thing: this quote may not actually belong to Knuth
There’s an interesting backstory.
The sentence is also often attributed to Tony Hoare (C. A. R. Hoare). Even popular quotation sites list it as Hoare’s quote.
Yet Knuth himself called it “Hoare’s Dictum” in his 1989 article “The Errors of TeX.”
Hoare, in turn, said it was not his statement but Knuth’s.
The two masters effectively passed the attribution back and forth, but based on documentary evidence, the accepted view is that it is Knuth’s wording, first appearing in the 1974 paper.
Regardless of who said it first, the important point is that its original meaning has been truncated and misunderstood.
Frequently asked questions
Q. So do I not need to care about performance from the start?
No. Decisions that determine structure, such as algorithm selection, require attention from the beginning. Knuth said to forget “small” efficiencies, not design-level decisions.
Q. When should I measure?
After you have working code. First make it run; if it is slow, use a profiler to find the bottleneck and fix only that area.
When you encounter this quote again, remember the rest: forget the 97%, but don’t miss the 3%.
Be wary of optimizing without measurement, but don’t back down when facing a real bottleneck. That is what Knuth really meant.
If there is code you were about to change today because it “seems slow,” try running the profiler first.

