99 comments

[ 3.3 ms ] story [ 177 ms ] thread
the prototype should be crazy fast. as soon as features are added, it's gonna be slowing down.
I think that's a really bad article. It's (as always) not that simple.

He says "if you want to build a really fast program, pay attention to the performance from the start.". So it's a business requirement from the start (to build a really fast program). That's fine and should be taken into account for development. Put it in your definition of done, start with performance and regression tests or something like that to pay attention to this particular business requirement. Have checks for your performance requirements and handle them as any other requirement for your software.

But most projects simply don't have that requirement and that's fine. Sure, your project will fail if it's unusable and slow but it will also fail if you put your efforts into unneeded optimizations from the start and slow down development of other features. I've seen projects fail due to premature optimizations in the beginning.

Yeah I think if you want performance, the more important thing to do from the start is focus on loose coupling and separation of concerns. The idea is that when you do want to optimize performance, you want it to be easy to isolate critical sections, measure them, and make improvements. Premature optimization is just going to make progress slower, and you might not know what bottlenecks you will end up creating until the project is farther along.

There are also some basic things you can keep in mind from the start: like if you need predictable performance then you should avoid choosing a language with stop-the-world garbage collection.

This is a very good point. In many projects, performance is not just relevant. Of course it makes sense to follow good practices and not make things slow on purpose, but thinking a lot about performance when it is not exactly a goal doesnt make sense.

On startups, I think there is a fine balance. You have to focus on many things, performance might be critical or might not depending on the business case. You have to think about where to spend your focus.

I disagree. Performance is almost always an implicit goal. People don't state it very often because it's so obvious. Why wants slow software?

But more importantly this article is a rebuttal to people saying "we can optimise performance at the end". They aren't saying "We never intended for it to be fast and we aren't going to bother trying to do that." they're saying that performance is a goal. Look at the examples he screenshotted. Nobody says "dude, performance isn't a goal of this project; you just have to live with it being slow".

Good enough performance is the goal. If the latency is 100-200ms, then it is often not a big problem if your request cycle is 30ms instead of 3ms. Unless you expect heaps of traffic, then the 10x performance improvement means a lot.
Lets be realistic, no "apps", front end websites etc are hitting sub-second latencies for anything. Hacker News, and the linked article are stark exceptions where the page load itself was under 200ms for me. Posting this comment of course took about 3 seconds. The amount of latency in the modern web is fairly astounding if we're being honest.
> Lets be realistic

Ok.

> no "apps"

Sure?

> Hacker News, and the linked article are stark exceptions where the page load itself was under 200ms for me

So let's be realistic (sorry :) ), it is possible, but it needs to be a strong requirement up front as its going to dictate a lot of choices that are hard to re-evaluate down the road.

> The amount of latency in the modern web is fairly astounding if we're being honest.

We can totally high-five on that one. One thing I feel contributes here is that good devs are expensive. So we prefer them to use tools that help m to deliver quickly. Super low latency stuff usually incurs build times, this is not making your devs more efficient. Also less good devs find it often harder to produce optimized code "by default".

I can’t work out if you’re attempting to be a dramatization of the problem or not. Low latency developing “incurring build times” in particular doesn’t make a lot of sense. It just takes considered design, nothing about the result is necessarily expensive.
I've programmed web stuff in rust and in rails. i can tell you that build times (and REPL on error, and a console with DB connectivity, and lots of pre-existing modules/libs/plugins) do matter.

We can get all that stuff in Rust (C/C++/Zig) too, but it is simply not there yet.

Only Go is both run time efficient AND compile time efficient.

My point: all is possible at unlimited resources, but that's unrealistic.

Go is a delight to work with, if you solve new problems in your own way. Not so much unfortunately solving same old problems again, ie. SOAP/XML and similar.
I came here to mention the exact same line:

> if you want to build a really fast program

What's meant here? Is "want to build" a requirement? And what does "really fast mean?

I'd say you need to look at this per project. Sometimes "fast enough" means you can store most things in an RDMS, sometimes it means you need Redis. Sometimes fast enough means you can use Ruby, sometimes it means you need C/C++/Rust.

It's all trade offs. Having all data in RDBMS makes a lot of things easier (manage infra, manage local dev setups, transactions, joins, etc). Having Rails for web dev can get you from zero to wow pretty fast (lots of plugins, quick rebuilds, REPLs on errors, a console with db connectivity for trying the code yr about to add). These two can save a lot resources on development.

But dont expect to out perform an app that uses Rust+Redis.

Know your project, and know what is commonly picked to attack such a project. This is much better advise than "dont compromise on performance".

The problem with old, out-of-context quotes is that they are old and out of context.

The Knuth quote is from 1974 and is preceded by the not unimportant statement that "Programmers waste enormous amounts of time thinking about, or worrying about, the speed of noncritical parts of their programs."

What is considered "noncritial" in a modern CRUD web app might not be the same as an algorithmically dense program written in assembler for a PDP-11. For example, it's going to be very difficult to optimize away the frameworks you depend on to make your app feature complete to begin with.

> but it will also fail if you put your efforts into unneeded optimizations

One thing is going extra lengths to achieve a few extra speed points, but there's also a much simpler path to a reasonable optimization: simply making sure that you don't do stupid and unnecessary things along the way.

I far too often see in apps and when reviewing code that things are slow not because they lack some complicated extra optimization, but simply because they were carelessly written. Whether it's n+1 query problem, or loading files/passing huge json/building complex objects on each iteration - these are all things that don't require any special effort other then thinking it through a little and paying some attention to details. Not just that it can make an app a lot faster, being careful about this will almost always simplify your code and actually make it easier for understanding and maintenance. And it takes close to zero extra time to any decent programmer.

And yet a lot of younger devs intentionally don't care because they basically misinterpret Knuth's advice and think that giving any thought about performance until the very end of project is a waste of time. I had more than one argue over this in code reviews.

First rule of optimisation is don't optimize!
As I see it, performance only matters if you're losing more customers or users over it than you gain by having spent that effort on features. And hardware is cheap nowadays. This is also not a linear relationship, performance focused development generally constrains the system which makes refactoring harder which makes new features harder (because you almost certainly did not get the architecture right the first time around).
>And hardware is cheap nowadays.

Cheap and available (and correctly setup) are not synonyms, however.

In the years I observed how - generally speaking - programmers (correctly as it is their work) tend to have the best of the best in hardware (and a fast LAN, and a fast WAN, etc.) so locally where the program is developed it feels fast, responsive, etc.

But the user base may have older processors, less RAM, slower mass storage and slower WAN/Internet access, so at their end the same program will appear slow, in some cases so slow to make it unusable.

I always thought that at the developers there should exist a few reasonably old machines possibly with installed the same services/other tools that the client target machines normally have where the program should be tested for excessive increased slowness compared to what happens on the development machines.

Thankfully, Travis, Azure Pipelines and Appveyor are slow as molasses and if you are forced to wait for them before merging a commit you will optimize the speed so that at least CI is reasonably fast.
I agree with most of what you said, except hardware isn't really all that cheap. I used to think so, but recently have run up against some "that's all this box can do?" and "this throughput costs this much?" and "why is this so slow" with fairly good algorithms but a lot of data and rps. So I've been a tad more perf forward lately than in the past.
So the story should better have been: Develop a sane architecture which is fast by design but do low-level performance optimizations at the end
Electron out?

But a fast product that doesn't ship will also die.

> If someone says:

>> "We are building programs correct first, performant later. We will optimize it after it’s feature complete."

> It actually means: performance would stay mostly the same, unless those people find some low-hanging fruits that will allow them to make the program fast without changing too much of what they’ve already built.

I agree with the premise, but not (always) with the overall conclusion of the article. If you go preformance-first, you should also go security-first, usability-first, and accessibility-first. All of those factors are harder to implement afterwards than when it's being done from the beginning. But there's also the other side - you may come up with a performant, secure, usable and accessible application that is lacking core features, making the product useless. There's no silver bullet, but _not_ going performance-first is totally fine in some cases (especially prototypes / MVPs).

I think this is terrible advice. There's plenty of ways to write highly performant, wrong sofware, that contains bugs. What's worse than a slow program? One that doesn't run. 1/10 of the time. Whats worse than a program that runs 1/10 of the time? One that runs with high uptime and resiliency, but handles funds with the wrong sign.
Is it really terrible advice for anyone to actually think about performance when programming.
No, but you usually don't know what will be the poorly performing part or in need of optimization, beyond the macro level. Don't check your brain at the door, but don't overthink it too early.

Someone else cites old systems with core decisions that are unchangeable because a data structure or algorithm is central to the entire codebase, as an example of "should have thought of performance earlier". My reaction to that was: why is the code structured in such a way that a particular data structure or algorithm is central to the entire edifice.

I think the error the article makes is in describing later performance improvements as "accidental" and low hanging fruit, which is nonsense. If your code can't handle continual refactoring, including to realize significant performance gains, then you have a deeper problem than performance.

yes. Because for most programmers, who are basically becoming webdevs, the internet is now a distributed system, and when you try to use old "performance" algorithms, you're going to be in a world of hurt when suddenly things are distributed and asynchronous. Advice about what algorithms have what big-O goes out the window when you're in a distributed system. Just use what works, what your framework provides, because smarter people have solved this problem, the network is your bottleneck anyways.

Just like "don't roll your own crypto" probably "don't roll your algos" is pretty sound advice for most programmers in 2020.

Yes, I know not everyone is a webdev, but the median programmer receiving advice is.

I hope he doesn't build software like that website
What do you dislike about it?
I believe OP is referring to the terrible readability and color contrast, with that background color.
Terrible contrast? Firefox's accessibility inspector gives the text a contrast ratio of 15.17, with 4.5 being the minimum for what qualifies as good and 7 as the recommended minimum for good readability.

I change text colours in the web inspector a lot because plenty of websites these days are medium gray on light gray with a font-weight of 100, but this clearly isn't one of them. It's fine to say you don't like the colour, but the contrast is great.

Not to mention you can always toggle reader mode if you don't like the aesthetic choice of a blog.
I like the site a lot. It doesn't look like most sites and it is easy to read.
performance first? accessibility first? mobile first? security first? correctness first? ...

There can only one thing come first, that's the definition of the word "first". You know what I do? "refactorizable first". Keep your code in a state that refactoring things is relatively safe and then you can work on the problems when they appear.

Look how fast this program is:

    int main () {}
Screenshot. Printed. Framed.

Seriously, this is it for most projects. By most I mean “only” 99% in the context of my personal experience, but not all.

Using performance as a synonym for only runtime speed doesn't feel satisfying. Shouldn't we include quality of results, such as correctness and fulfillment of requirements, in the evaluation of whether a program performs well?
Performance has a variety of contextual meanings. Market performance would be an example. When talking about execution performance, we're usually talking about speed/smoothness, under the assumption that a program is already correct and complete. If we overload this to include basic correctness, we would need another term to capture these other qualities.
But we are using other, more precise terms already, no? Speed, fast, slow.
I think author also optimized the time it takes for users to click `ctrl+w` from his side. That yellow background is terrible, it gave me a headache.
I couldn't agree more. Not only did he fail to understand the problem, he made his site so headache-y, I hit ctrl+w asap. It's just another guy with access to broadband internet trying to get his 1 minute of internet fame.. luckily, there's nothing to be learned in that "article".
Similarly, as Jeff Atwood put it: "performance is a feature"

https://blog.codinghorror.com/performance-is-a-feature/

Performance takes time and intention. It needs to be planned for _like it's a feature_ or it won't get worked on. Usually this means working with business analysts to communicate to your customer that performance needs to be thought of like a feature -- AKA given its own time and effort and space.
Often perf reqs dictate the systems/languages/FWs that may be considered. Thus these reqs are very important to be known up front.

You can add many features later, but some level of perf is hard once you have 50k line of app code on top of, for instance, Rails. This because it's hard to change language/FW, compared to adding a new functionality on top.

Indeed, and like any feature, it must be considered against other features and have its priority determined through user research and cost-benefit analysis. It's not an end goal for its own sake. Maybe it's more important than delivering new functionality. Maybe it's not.
I'm not sure if performance has to be first. One could for example do proof of concept style of work with some higher level language before starting to create the actual product which then should also take the performance aspects under consideration.

I think we actually waste a lot of energy by not encouraging our selves to pay attention on the performance. Nature sort of demands efficiency in long run. Yes?

This article makes a strange assumption. That you know perfectly the end result before starting the process, which is a rare case in my experience.

Normally, a product will start with a small feature, and all sorts of random stuff will be added to it to make it grow. Some of them will be abandoned, as they'll fail commercially, and some will expand as they bring money or attention. Creating an architecture that can allow that kind of expansion without crumbling over tech debt is the challenge.

Ultimately, some programs can be reduced to a simple operation, and that can be designed from the ground up to be really performant. Something like the silver searcher (https://github.com/ggreer/the_silver_searcher) or ripgrep (https://github.com/BurntSushi/ripgrep) have the advantage that they have laser-focus in what they want, and designed to take advantage of that. Most of the developed software have way broader objectives.

The important part of "premature optimisation is the root of all evil" is PREMATURE. Don't optimise things that is still uncertain that required to be optimised. When performance is critical OF COURSE optimisation is a requirement.

There's a middle ground. I like to say "fast is a feature" or "it's not done til it's fast". Getting the feature working is a first step, but shipping a slow feature is never ok.
> The important part of "premature optimisation is the root of all evil" is PREMATURE.

Right -- I think the examples he's arguing against have slightly misunderstood what "premature" means. The quote is supposed to mean, "Don't optimize until you know that optimization is necessary." The people in his examples are interpreting it as, "Don't optimize until your program is feature complete". I doubt Knuth would agree with that principle. If people are raising tickets saying that some feature is slow, then you know optimization is necessary, and it's not premature any more.

That said, as with any proverb, you have to use some common sense. If you know you're going to be doing key-value lookups in a data structure that's going to contain hundreds of thousands of pairs, it's OK to start off with a hash table, rather than starting with flat list + linear search and switching over only after benchmarking.

The colours of this page are an unfortunate choice tbh...
I picked up a codebase where people were optimising for performance throughout the development it's now very hard to change or refactor because there are preemptive performance optimisations and caching everywhere (front and backend).

It makes far more sense to create an extensible solution and then identify and fix the bottlenecks as the vision about the "final product" (or version x) becomes more clear.

I work on systems where speed is a requirement, and this think-about-speed-from-the-beginning is the way to proper way to do this.

I've also been parachuted into projects that are having performance problems, and usually you can find some nice low hanging fruit. But there's usually some crucial poor-performing part that can't be made faster without a complete rewrite that uses a entirely different algorithm and data-structure. And then it becomes clear that doing so would impact all the other code; basically, its unfixable because of early design choices.

Most of the slowest programs I've had to crawl into have been 'designed for web scale' nonsense from the beginning, and die a horrid performance death through premature distribution and the use of 'scalable' nosql technologies that were much talked about when the project adopted them but now are rather out of fashion, thankfully. My experience is that ipc is bad for performance and having a system on as few boxes as possible is good for performance, which seems to be quite the opposite to the system architectures that were all the 'web scale' rage this past decade.

And speed is always a requirement. There are tons of studies you can look up about the impact of page load time on e-commerce revenue.
TBH the specific examples I had in mind when I was writing my post were mostly backend systems, including batch ones. A lot of the performance improvements I extract from software is by dividing up what needs to be fast and what can be slow, and slowing down the slow stuff to free up resources for the fast stuff etc. I just chuck this in because I think its interesting how many perspectives and directions people on HN have.
Not everything is Customer facing, interactive systems though.
I think of performance in a different way: "don't do stupid things" is my mantra. In other words, while not focusing on performance right away, I avoid doing stupid things. This lets me produce software which runs surprisingly well, spending very little time on improving performance.
(comment deleted)
All the performance in the world doesn't matter if your software doesn't work, doesn't do useful things or isn't complete.

Plenty of good, useful software that is well used is kind of slow. I don't know anyone using anything that's very fast but incorrect or unfinished software.

> All the performance in the world doesn't matter if your software doesn't work, doesn't do useful things or isn't complete.

And all the functionality in the world doesn't matter if it can't deliver a result by a deadline.

I'm not convinced there's much (non-real-time) software where performance places legitimate constraints on deadlines.

I've seen exactly one case before, which was an ancient script running on a mainframe in a bank which took 6 hours to complete overnight. [And, by the way, correctness is still more important in this case!]

But 99.999% of the time, your code's performance is not the final word.

Here's one:

"1 second of loading lag time would cost Amazon $1.6 billion in sales per year." ~Amazon

Here's another:

"An extra 0.5 seconds in each search page generation would cause traffic to drop by 20%" ~Google

Both of those pre-suppose that the software already exists and is already doing things correctly.

Non-functioning software would cost Amazon all of it's sales per year.

Why make the assumption that performant software and functional software are somehow on the opposite side of the spectrum of what's possible?

The point of the article is that performance is just as important to consider in addition to functionality and correctness. To use an analogy, it's easier to make a house energy efficient if its considered from the beginning, than if it's tacked on afterwards. In fact, tacking it on afterwards is sometime impossible without a complete renovation (analogous to re-writing the software).

> is well used is kind of slow

And users hate that the software is slow, and wonder why it has to be that way, but grit their teeth and deal with it because they feel like they don’t have an option. And, until software professionals start behaving like actual professionals, they won’t.

Clearly from your comment the software is so useful that despite hating it, the users deal with the slowness. Which to me only reinforces they parent's point: correctness and availability is more important than speed. If speed were the most important thing then they wouldn't just hate it, they wouldn't use it.
Slippery slope here is, how far does one take performance first design?

I’ve seen too many devs rely on caching as the upfront solution. That’s performance first design, right!?

> I’m saying these improvements are accidental. It’s sheer luck they happened.

No. They're not accidental. They're entirely intentional, done by sheer hard work.

On a related note, I am surprised a person who claims to write about UI design has a website with that background color. The contrast is just awful.

Of course you should consider performance when you start a project - if your language, framework or core design is slow it seems unlikely you'll be able to do much to improve it later. You need to at least think about it.

But I don't think "Premature optimization" is synonymous with "performance". Optimizing or perfecting every detail of a feature that might still go through significant changes over time seems risky and wasteful.

If the author had said, "Performance & functionality over beauty" it would have made more sense.
The author here seems to be missing the basic point of the phrase. Others have correctly noted that performance is a feature, but even with that taken for granted, it is not often apparent what the constraints of the full system are until they've been built. You may try and guess, but you're more likely to guess wrong than right. Look at OSes, ISAs, DBs, etc. All of those have been rewritten numerous times not because the originals paid no attention to what performance would be like, but rather because they did not know how to improve performance until they had something they could test.
High performance code can often be an order of magnitude longer and more complex to write than moderately performant code. When you're not even sure what you're building yet, aiming for performance first is a waste of time and a good way to ensure you end up not realising anything at all.

Optimise for what's important for your specific project. Maybe exploring the design space is the priority to start. Maybe releasing before the end of the year is more important.

Not all projects are the same so it's pointless to argue about general rules like this.