I used to believe this seemingly obvious truism, but it turns out that it's not at all easy to rewrite your entire architecture when it's slow by design, especially if the design flaws are baked into the public API. https://twitter.com/BrianGoetz/status/1246054109762990087
Part of the problem is that the very paradigms we use are mostly slow by design. OOP, RAII, FRP, ARC, GC… All of these require masses of runtime heap allocations and deallocations, and actively work against the CPU cache.
It's almost impossible to write fast software using the idiomatic programming patterns encouraged by most mainstream languages. Even "low-level" systems languages like C++ have adopted patterns that fight against the CPU and compiler's ability to optimize your code.
Basically the only folks who still write fast software are AAA game engine developers, and they mostly use a very limited subset of C++ consisting of flat arrays (for cache coherence) and small structs, with arena-based custom allocators to avoid malloc/free inside hot paths.
While it's true most code doesn't have the same performance constraints as games, I don't think most programmers have any idea just how slow their code actually is. We see benchmarks that show Java is 2-3x slower than C++ and think that's basically fine. But that's not accurate.
*Idiomatic* code in OOP languages is all roughly equivalent because most of the overhead comes from allocations and cache misses. But that idiomatic code is 200-300x slower than the CPU is capable of. That's like downgrading your 3GHz processor to 10MHz.
What makes a low-level language "low-level" is not that code you write in it is automatically fast, it's that it has low-level primitives necessary to write fast code *if you use them correctly*. Higher-level languages often don't expose these at all, so fast code is impossible.
So what does this have to do with writing clean code? It's about the definition of "clean". In OOP we define "clean" as meaning that code is all separated into modules that communicate via protocols. Exposing the internal layout of data is considered an antipattern.
But this interface-oriented approach to software is antithetical to writing fast software. To make software fast you have to think about the data first. If you leave that to the end, chances are that you'll have designed your interface in a way that prevents efficient data flow.
I don't really know what the solution to this is. Data-oriented design is at best a niche field with minimal info available online and very little in the way of mainstream language support. And game developers don't exactly have a culture of automated testing we'd want to emulate
But it doesn't seem sustainable for the software industry as a whole to continue down a path of defining "best practices" that are diametrically opposed to efficiency. Computers aren't really getting faster anymore.
You can follow @nicklockwood.
Tip: mention @twtextapp on a Twitter thread with the keyword “unroll” to get a link to it.

Latest Threads Unrolled: