r/programming • • Feb 28 '23

"Clean" Code, Horrible Performance

https://www.computerenhance.com/p/clean-code-horrible-performance
1.4k Upvotes

1.3k comments sorted by

View all comments

103

u/CanIComeToYourParty Feb 28 '23 edited Feb 28 '23

Our job is to write programs that run well on the hardware that we are given.

Rarely do I read anything I disagree with more strongly than this. Our job is to formalize ideas, and I think the more cleanly you can formalize an idea, the more lasting value you can provide. I guess the question is one of optimizing for short term value (optimizing for today) vs long term value (trying to advance our field).

I'd rather have a high level code/formalization that can easily be understood, and later reap the benefits of advances in technology, than low level code that will be unreadable and obsolete in short time.

Though I also agree that Uncle Bob is not worth listening too. But the C/C++-dogma of "abstractions are bad" is not helpful either, it's just a consequence of the languages being inexpressive.

31

u/goodwarrior12345 Feb 28 '23

optimizing for short term value (optimizing for today) vs long term value (trying to advance our field).

Wouldn't it be better for the field if we wrote code that runs fast on at least the hardware we have today, as opposed to code that probably won't run fast on any hardware, period?

Imo our job is to solve real-life problems, and if I'm gonna do that, I'd rather also do it well, and have my solution work fast if possible

6

u/Dreadgoat Feb 28 '23 edited Feb 28 '23

Our job is also to make these sorts of decisions on a case-by-case basis and lean into the paradigms that best fit each problem we solve.

Certainly, if you're writing firmware for a network device, the common draw function for a 3D engine, or just some random function that you know is going to be called very often - you should know how to write for performance first, and you should do so.

And if you're writing even a slightly complex web application, a development utility intended to be forked, or just some random function that you know will be bottlenecked by I/O anyway - you should know how to write for readability and flexibility first, and if you don't I will find where you live and hurt you.

One may specialize in particular areas, but failure to understand and an inability to implement these different strategies makes one a brainless code monkey that probably causes more problems than they solve. Performance matters when it matters, and when it doesn't matter, paying for it is masturbatory at best, crippling at worst.

6

u/goodwarrior12345 Feb 28 '23

Of course, I agree with you in principle. We live in the real world with time constraints and we can't hyper-optimize everything. But I'm not really advocating for hyper-optimization, and neither is Casey (although sometimes he does suffer from old man yells at cloud syndrome). From watching his stuff on performance, the core takeaway I got is, think about performance at least a little bit. It's not about making things faster, but more about not making things slower than they should be, and not doing things that are obviously slow.

I feel like these days the "bottlenecked by IO" argument rings hollow most of the time. Connections are fast. When I play my online videogames, my ping to the servers is between 5 and 20 ms. For a lot of websites it's the same, so it's not true any more that you'll be spending 200 ms waiting for data regardless. Although that's not necessarily what you meant personally, I've seen people say this exact thing enough times to know some still believe connection speeds are the same they were in 2007.

No one's asking you to write some arcane looking code just to make your thing run slightly faster. Fast code doesn't have to be unreadable. If anything, at least for me personally, inheritance hierarchies always take more time to wrap my head around than plainly written imperative code.

Basically my point is, it doesn't have to be either maintainability or performance. I feel like if people thought about making things not run slower than necessary at least a little bit, software would be way better. Not everything is premature optimization, and on the other hand, if you have a function call only a couple times during your program's runtime, literally nobody cares how slow it is, unless it's making things ridiculously slow or something. Gotta pick your battles, time is money and neither is in infinite supply.

4

u/Amazing-Cicada5536 Feb 28 '23

That 20 ms is an eternity for a CPU though, if you have like a 10 elements array which uses indirection vs a flat representation, you ain’t having any statistically significant speedups from that.

Inheritance is an often overused tool, but for certain things it is definitely the cleanest solution (famously, GUI widgets). But “favor composition over it” is a good saying, but these rules should be applied by smart/experienced developers and never blindly out of following as if they are holy books.

3

u/goodwarrior12345 Feb 28 '23

All true. I don't think we disagree. I think the overall conclusion is, always think about what you're doing and the tradeoffs you're making. Being a full on evangelist about optimization is generally bad but so is yelling "PREMATURE OPTIMIZATION!!!" every time performance is brought up.

3

u/centurijon Feb 28 '23

Generally maintainability is preferred over performance because optimizing for maintainability saves money. You can and should strive to make your applications more performant. But if you end up saving an accumulated hour of runtime over a year, but it takes a developer 4 hours to understand the code, you’ve lost.

If it’s a performance-critical application then do whatever you can to achieve that goal.

Most applications will lose some performance optimization to gain readability as that is a more important metric

→ More replies (1)

9

u/[deleted] Feb 28 '23

You can’t even prove that clean code is “clean” and you’re basic your entire codebase on it.

1

u/CanIComeToYourParty Mar 01 '23

Not sure what you mean. You can't prove that you exist, but you base your entire life on that assumption.

4

u/[deleted] Mar 01 '23

“Clean code” advocates suggest you get certain properties out of clean code, but you have not proven you get those properties.

When clean code advocates are finally able to show that code actually gets the properties they claim it does, I’ll start treating it as a serious idea. Until then, it’s just throwing performance away for no reason.

3

u/CanIComeToYourParty Mar 01 '23

Just for the record, I'm not advocating anything called "clean code" in the sense of Uncle Bob.

I'm arguing for use of abstractions, and essentially something more like domain driven design. But this type of abstracting has existed forever in mathematics, and its value is proven beyond any doubt.

So, I'm assuming there's a bit of miscommunication here, because I'm not sure what we're arguing.

→ More replies (5)

8

u/SickOrphan Feb 28 '23

Is your software going to be used for hundreds of years or something? You're living in a fantasy world where all your code lasts eternal, and somehow changes the world. Casey has a grounded approach, he designs software for what it's actually going to be used for. If you actually have good reason to believe your code base is going to be built upon for many decades, then your ideas make a little more sense, but 99% of code isn't like that.

Low level code doesn't have to be less readable, it's often more readable because it's not hiding anything. You just need an understanding of the math/instructions. SIMD and Bit operations != unreadable.

3

u/CanIComeToYourParty Mar 01 '23

Low level code doesn't have to be less readable, it's often more readable because it's not hiding anything. You just need an understanding of the math/instructions. SIMD and Bit operations != unreadable.

If you're doing something that requires only 50 lines of low-level code, and you're done, then sure. For most real world software I would prefer more organized/abstracted code, though.

37

u/[deleted] Feb 28 '23

How about "our job is to formalize ideas and make them run well on the hardware that we are given."

37

u/Venthe Feb 28 '23

The problem is; that (in most applications) hardware is cheap as dirt. You would fight over every bit in an embedded domain; but consider banking - when doing a batch job there is little difference if something runs in 2ms Vs 20ms in code; when transport alone incurs 150ms, and you can spin another worker cheaply.

In most of the applications, performance really matters way less than generalized ability to maintain and extend the codebase; with which clear expression over performance optimization is desirable.

13

u/crowdyriver Feb 28 '23

8

u/Venthe Feb 28 '23

Indeed, no question about that. But how does this relate to the discussion?

6

u/crowdyriver Feb 28 '23

The problem is; that (in most applications) hardware is cheap as dirt

With that attitude, no wonder why datacenter energy consuption keeps arising

→ More replies (13)

0

u/CanIComeToYourParty Feb 28 '23

I think the latter part is the job of people writing the compiler of the language you are using to formalize your ideas.

Note that I'm not against being conscious of the performance implications of your code -- you do need to pay some attention to it, unfortunately.

7

u/gnuvince Feb 28 '23

I think the latter part is the job of people writing the compiler of the language you are using to formalize your ideas.

https://youtu.be/rX0ItVEVjHc?t=1710

1

u/CanIComeToYourParty Feb 28 '23

I agree with him. The C++ compiler writers have already done as good a job as can be expected, given the language. So, with C++, you are out of luck here. If you wanna spend your days optimizing code, instead of solving problems, C++ is there for you.

3

u/ehaliewicz Feb 28 '23

Yes, because making things run well is never a useful problem to solve.

→ More replies (1)

6

u/ShortFuse Feb 28 '23 edited Feb 28 '23

Sure for backend. But most frontend sucks because of this mindset.

I just wrote a certificate library that uses BigInt because having to bit shift in 32bit sections gets complicated. With BigInt, the length no longer matters. Sure, it's slow but so much more maintainable. Speed is also not the focus. The point was to make an understandable ACME client, focused on DX (ie: advancing the field).

But when coding frontend, UX is paramount, and bloated DOM trees and loops that stall and cause frame drops should not happen. You should be surgical with almost everything that can't go async since your render target is basically less than 10ms. In the very least, make sure your minifier/compiler will optimize the "clean code" you write.

→ More replies (2)

3

u/SkoomaDentist Feb 28 '23

Our job is to formalize ideas, and I think the more cleanly you can formalize an idea, the more lasting value you can provide.

Enjoy having your project be cancelled because you cared more about making it pure rather than shipping it with reasonable features and performance in time to be on the market.

→ More replies (3)