Premature Optimization: How Donald Knuth "Skill Issued" Dijkstra

5 hours ago 1

Donald Knuth is quoted as saying:

Premature optimization is the root of all evil.

Today we're going to chase that thread.

In doing so, we're going to uncover the story of when Donald Knuth "skill-issued" Edsger Dijkstra.

But first we have to figure out—

What is "optimization"?

Quote Attribution Is Hard

So what is "optimization"?

This etymology site has a definition dating back to 1844: "to act as an optimist, take the most hopeful view of a matter, a back-formation from optimist."

Which, it's honestly hilarious to imagine the stereotypically pessimistic computer scientist getting all upset off at that definition.

But, anyway, it's clear that the definition has morphed over time. We usually think of optimization as "to make the best or most effective use of a situation, opportunity, or resource."

We programmers love optimization. Maybe a little too much.

Which brings us to one of, if not the most popular quote on optimization—

Premature optimization is the root of all evil.

The full quote, which can be found is Donald Knuth's paper, Structured Programming With go to Statements, as well as in his book The Art of Programming, actually includes a preface—

We should forget about small efficiencies, say about 97% of the time: Premature optimization is the root of all evil.

We've all been there. We've all gone on an "optimization" spree. Sometimes it's hard to know when and where to stop.

And this "mode" that we're in–it doesn't have to be called "optimization". What you're over-doing might fall more neatly into the "abstraction" bucket, or perhaps the "systematizing" bucket. You might be doing any or all of these higher-level activities prematurely.

But, it might come as a surprise—

Donald Knuth, of programming fame, does not actually claim authorship of this quote! Instead, he tries to cite Sir Tony Hoare.

But... Sir Tony Hoare denies authorship as well!

Hans Gerwitz looked further into this and went so far as to email Sir Tony Hoare, who replied:

Dear Hans,

I’m sorry I have no recollection how this quotation came about.? I might have attributed it to Edsger Dijkstra.

I think it would be fair for you assume it is common culture or folklore.

Tony.

Of course. We should have known that this rabbit hole would lead to Edsger Dijkstra, the unofficial king of programming simplicity and pessimism.

Go To Statement Considered Harmful

On March 1st, 1968, Edsger Dijkstra wrote a letter to the editor that would rock the programming world.

It was titled, Go To Statement Considered Harmful.

It starts with what is basically an abstract:

For a number of years I have been familiar with the observation that the quality of programmers is a decreasing function of the density of go to statements in the programs they produce. More recently I discovered why the use of the go to statement has such disastrous effects, and I became convinced that the go to statement should be abolished from all "higher level" programming languages (i.e. everything except, perhaps, plain machine code).

In other words, Dijkstra didn't like goto statements. If you're writing assembly? Fine, they're a common and necessary feature of machine code. But he believed that in higher level languages, goto statements are a sign of bad abstraction and lazy reasoning.

These unrestricted jumps (via goto statements) in your program made debugging and testing much more difficult. Dijkstra was a purist, and he saw first-hand how these jumps could lead to logical-flow-nightmare (what we might think of as spaghetti code).

This letter by Dijkstra inspired hundreds, maybe even thousands of responses, often taking the form of "Considered Harmful". E.g., Frank Rubin wrote a piece called 'GOTO Considered Harmful' Considered Harmful. A bit more recently, Eric Meyer wrote "Considered Harmful" Essays Considered Harmful.

Usually the "Considered Harmful" critiques are criticisms of the more "unintuitive" features of programming languages. Python decorators, macros, calls to super—go to statements were just the beginning.

Skill Issue

In December 1974, almost 7 years after Dijkstra dropped the "Go To Statement Considered Harmful" bomb on the computer science world, Donald Knuth published Structured Programming with go to Statements.

I really, really, really like this essay by Donald Knuth. It's such a precious piece of programming history. It really captures the essence of programming—riding the line between logic, abstraction, language, and programming as a trade-skill.

He begins with the intro:

A revolution is taking place in the way we write programs and teach programming, because we are beginning to understand the associated mental processes more deeply.

Let me translate this to modern speak:

Skill issue.

Dijkstra just got Knuth'ed.

Now, what I really find compelling about this whole exchange is that it's such an iconic moment in the evolution of programming as a trade.

Programming was in its infancy. It didn't have the decades, or centuries of wisdom that other skills have had, have nurtured, and have passed down. I'm talking carpentry, masonry, painting, etc.

We, as a collective programming entity, had to gradually build up a better understanding of the "mental processes" that go into writing code.

At first we didn't really know how to communicate human concepts to computers. We had to really force our brains into the world of bits. But as time went on, we understood the tradeoffs better. Over time we built up a whole pantry full of mental heuristics (of which include "Premature optimization is the root of all evil") and acronyms (YAGNI, DRY, SOLID, et. all).

This all happened pretty quickly, actually. So quickly, in fact, that it makes me wonder if we're still pretty bad at writing code. (I'm pretty we are.)

Programming has changed a lot since Donald Knuth wrote his response to Dijkstra.

We've already talked about how we've developed a better mental model of programming, and created many helpful heuristics.

But another way that a skill can improve—whether it be carpentry, masonry, or programming—is with the advent of new and improved tools.

But is it that simple?

Carpentry got "better" when power tools were invented, right? Or at least more efficient. But, still, some of the most beautiful, strong, and long-lasting carpentry involves lots of care—the type that only hand tools can provide.

New tools always come with a tradeoff.

I'm reminded of Tim Ewald's talk on Clojure: Programming with Hand Tools.

Just reading the title of that talk, you sort of get the point I'm trying to make. Writing in Clojure is hard, but it inspires Tim to write careful, well-crafted software.

At the risk of sparking a programming language argument, the programming languages of today are definitely "better". But that doesn't mean they force you into writing better code. Most languages, especially the higher-level ones, inspire more freedom, are more concise, and allow programmers to be much more productive—all of which might actually make the go to statement issue worse! There's more handing over of logical flow than ever before!

I'm of the opinion that, by and large, Dijkstra was right when it comes to the abuse and misuse of go to statements, and he would be appalled at much of the Python, Ruby, and JavaScript code that is running in production.

So yes, we built better languages, but of course you can still abuse them. There are early returns, Node.js callback hell, or if you're really masochistic, there's Java.

There are also other tools—IDEs, language servers, Intellisense to name a few—that fundamentally change the landscape of how we deal with control flow and code navigation. It’s easier than ever to jump around a codebase with “go to definition,” fuzzy file search (CMD + P), or command-line tools like ripgrep. These tools allow developers to jump around projects with great freedom. With this degree of code-navigation freedom, it might even encourage more logical jumps—not fewer.

But, these are all skills. And the skills, alongside the tools, have definitely improved. There is a lower barrier to entry (programming learning resources are available online, oftentimes for free!). The knowledge is passed on. And as a result we are more resilient when it comes to logical jumps. We use the tools and hone our skills, and together have a developed a higher tolerance for the poison that is go to statements.

Automating The Art of Programming

Unfortunately, I have to follow up the shiny new tools section with an AI section.

AI coding agents, and AI-based editors like Cursor or Windsurf help developers automate the writing of code.

Again, all tools come with tradeoffs.

I'm going to use the analogy of Japanese carpentry again.

The danger of using power tools for carpentry isn't that they're inherently bad, or that you should never use power tools. It's just that you shouldn't always use power tools.

Shoyan, the amazing carpenter whose YouTube I keep linking to, buys pre-cut lumber! Of course he does! And he uses circular saws and mitre saws, all sorts of drills and dremels.

But he also uses hand tools.

I guess, the AI generated boilerplate is the sawmill-cut lumber. You've gotta make sure it's good. You have to do quality control. And then you've got to seamlessly integrate it into the rest of your construction.

I'm sorry for the freezing-cold AI take.

There has been a mountain of content in every form of media about AI in programming. With each new tool, each new company, each new model, each new AI code editor, each new MCP server. Honestly, I'm tired—exhausted even—at reading people’s AI takes.

So really, I'm sorry. I'm not sure what the best way to discuss AI is at this current moment. So, let's move on.

Did Knuth Actually Get Dijkstra'd?

The ultimate layer of irony in all of this goes back to the origin of the root-of-all-evil quote.

Dear Hans,

I’m sorry I have no recollection how this quotation came about.? I might have attributed it to Edsger Dijkstra.

I think it would be fair for you assume it is common culture or folklore.

Tony.

That's right. The best guess Sir Tony Hoare had was that it was Dijkstra himself who deserved attribution—the very Dijkstra who inspired Knuth to write Structured Programming With go to Statements.

I suppose the takeaway here is that Dijkstra is always right, and we should take all of his thoughts as Gospel.

I'm mostly joking, of course. Sort of.

Optimizing Simplicity

As I wrote this post, I find myself overthinking the original quote:

Premature optimization is the root of all evil

I mean, of course I get it. But let me explain my confusion.

If I'm being pedantic (which I usually am), I can't help but get hung up on the fact that optimization simply must, categorically always a good thing. If optimization is ever considered bad, then you're not optimizing!

In my mind, that makes premature optimization sort of an oxymoron.

A true optimization would be one which is not premature!

I think a better motto might be:

Optimizing is always good, but you better be damned sure what you're doing is actually helpful.

Doesn't quite roll off the tongue. I'll work on it.

Maybe a better way to think about it is, like, what's your goal? When you're writing code, what are the vector(s) on which you're optimizing?

This can be wildly different depending on the context.

Donald Knuth, for example, was writing compilers when he talked about premature optimization being evil. In his context, it was, don't spend too much time and ruin your code's readability trying to get that extra 3% efficiency (as in run times, speed, memory usage).

In some projects, premature optimization might just mean: just parse the CSV—don't spend too much time on a one-off script. In that case, the vector of optimization really is just get the CSV parsed.

Do you just want to get the code to work? Great! But it might be hard to read or maintain or extend.

Do you want the code to be fast / efficient? Great! But it's probably going to be way more complex than an alternative, more legible, slower version.

That's sort of the thing, right? If you're truly optimizing, then there is no premature optimization, or over-optimization, you're just not optimizing!

I think most commonly, unless you're actually writing compilers, or low-level systems code, or maybe designing languages or open source frameworks, almost always the vectors you're going to want to optimize are:

  • How well does the code work? (I'll call this the Powerful <-> Useless vector)
  • How complex is the code? (I'll call this the Simple <-> Complex vector)
  • Time spent writing the code (not included in the image)

There are thousands of other vectors. Optimizing those at the right moments—well, that's the wisdom and the craft and the art of programming.

Anyways.

Here are some graphs.

Fig. 1
Fig. 2

In Fig. 2, if x is still the simple-complexity scale, and y is still powerful-useless scale, then, like 70%-80% of the time, you should stop optimizing for simplicity and powerfulness at the local maximum. That's the sweet spot.

But if you're astral.sh and you're building a fast Python type checker, then you'll shift way over to the far right side, seeking the highest global maximum you can find.

If you're a salesperson or manager who is vibe-coding to write a simple one-off script or hobby project, you might stop right there where we cross over the x axis.

It can always be different depending on the context.

Every Line Is a Potential Bug

I didn't really know where else to fit this in, but Thorsten Ball posted this on his weekly [platform-redacted-because-im-a-hater] publication The Register Spill, and I couldn't help but include it here.

Lawrence Kesteloot had this to say in his post, Every Line Is a Potential Bug:

Every line of code you write is a potential bug. Do not write any line of code unless you absolutely need it right now and your program will suffer for the lack of it. Do not write routines speculatively. Do not write abstraction layers you don’t need right now. If an optimization will add any complexity whatsoever, even a subtraction, resist it. You will be sorry in five years when your code is riddled with potentially-buggy code that you never really needed to write.

Programming Myths and Folklore

Whether it's Fred Brooks' Mythical Man Month or Silver Bullets, or lack thereof.

The grug brained developer.

A group of nerds meeting on top of a snowy mountain in Snowbird, Utah to write the agile manifesto.

Or Sir Tony Hoare attributing "Premature optimization is the root of all evil" to programming folklore.

Programming is full of myths and folklore.

This post (this one right here!) is going to be the first in a series of posts on programming folklore.


Subscribe FOR FREE if you liked this or hated it, or for some other reason want to read more!

Read Entire Article