Live data from Hacker News

“Clean” code, horrible performance

computerenhance.com

91–100 of 932 posts

Re: “Clean” code, horrible performance

#91
post #15

This guy is so dogmatic about it it hurts. I would argue that clean code is a spectrum from how flexible vs how rigid you want your abstractions to be. If your abstractions are too flexible for good performance, dial them back when you see the issue. If your abstractions are too rigid for your software to be extendable, then introduce indirection. We can all write code that glues a very fixed set of things end to end…

Casey is a bit of a hardcore crusader on the topic, but I'd hardly call dogmatic someone who can provide you evidence and measurements backing their thesis. The tests he put together here are hardly something I'd call a straw-man argument, they seem like reasonable simplification of real-cases.

Evidence in a micro benchmark of a single page of code.

The focus on performance here ignores the fact that most programs are large systems of many things that interact with each other. That is where good design and abstractions and “clean code” can really help.

Like all things it is about finding a balance and applying the right techniques to the right parts of a larger system.

Re: “Clean” code, horrible performance

#92
post #74

There is no doubting Casey's chops when he talks about performance, but as someone who has spent many hours watching (and enjoying!) his videos, as he stares puzzled at compiler errors, scrolls up and down endlessly at code he no longer remembers writing, and then - when it finally does compile - immediately has to dig into the debugger to work out something else that's gone wrong, I suspect the real answer to progra…

If you're talking about Handmade Hero, the real answer to programmer happiness is not using a language you despise and refusing to leverage the features of, not refusing to use libraries in that language or frameworks, not re-implementing everything from first principles, and to actually have your game designed first (not designing while you code.)

Re: “Clean” code, horrible performance

#93
Already in his first example, where he says he doesn't use range-based for in order to help the compiler and get a charitable result, he doesn't get the point, I think. You write code in a certain way in order to be able to use abstractions like range-based for, or functional style. If you are hand-unrolling the loop, or using a switch statement instead of polymorphism, you loose the ability to use that abstraction.

Esentially the whole point of object orientation is to enable polymorphism without having big switch statements at each call site. (That, and encapsulation, and nice method call syntax.) When people dislike object orientation, it's often because they don't get or at least don't like polymorphism.

Most people, most of the time, don't have to think about stuff like cache coherency. It is way more important to think about algorithmic complexity, and correctness. And then, if you find your code is too slow, and after profiling, you can think about inlining stuff or using structs-of-arrays instead of arrays-of-structs and so on.

Re: “Clean” code, horrible performance

#94

TL;DR: "Game developer optimizes code for execution as opposed to readability that 'clean-code' people suggest". There are few considerations: - most code is not CPU bound so his claims that you are eroding progress because you are not optimizing for CPU efficiency is baseless - writing readable code is more important than writing super optimal code (few exceptions: gaming is one) - using enums vs OOP is not changing…

I'm tired of every tool I install on my latest gen Intel CPU + 32GB RAM + NVMe drive machine being a complete slog. To each their own, but I don't find Casey's performant version less readable, I don't see the need for so many abstractions.

>I don't find Casey's performant version less readable

It does create implicit coupling. If you try to add a new shape you will run into the problem.

In the clean code version, your compiler will remind you to implement calculateArea

With his version you have to add a new `case` to every switch statement and hope you didn't miss one with a default case, because the compiler won't catch this one.

It's a crap way to code

Re: “Clean” code, horrible performance

#95

TL;DR: "Game developer optimizes code for execution as opposed to readability that 'clean-code' people suggest". There are few considerations: - most code is not CPU bound so his claims that you are eroding progress because you are not optimizing for CPU efficiency is baseless - writing readable code is more important than writing super optimal code (few exceptions: gaming is one) - using enums vs OOP is not changing…

I'm tired of every tool I install on my latest gen Intel CPU + 32GB RAM + NVMe drive machine being a complete slog. To each their own, but I don't find Casey's performant version less readable, I don't see the need for so many abstractions.

I think if you dig into why any of these tools perform poorly, you probably won’t find it’s because they were implemented using “Clean Code”, but rather that it’s down to a combination of many different things. I can’t say anything concrete because I don’t know which applications you are referring to.

But IMO framing it as clean vs performant is a mistake

Re: “Clean” code, horrible performance

#96
post #9

"Use subclasses over enums" must be some niche advice. I've never heard it. The youtuber seems to be referring to some specific example (he refers to specific advice from "them") so I guess there's some context in the other videos of the series. re: the speedup from moving from subclassing to enums - Compiler isn't pulling its weight if it can't devirtualize in such a simple program. re: the speedup from replacing th…

I think "them" is someone named Robert Cecil Martin, but I'm not sure if this example from the video appears in his book. What compiler are you using that devirtualizes every class hierarchy? I suspect that Casey is using C++ so he may (unfortunately) have multiple translation units in his program.

Martin Fowler's "Refactoring" also has "Replace Conditional with Polymorphism". I like the intent of the book but I don't follow it 100%. Another part of that book that tripped me is where he calls the same function with the same argument multiple times instead of saving the result in a variable for reuse.

Re: “Clean” code, horrible performance

#97

I don't think there is a contradiction or surprising point here. At least my understanding of the case for clean code is that developer time is a significantly more expensive resource than compute, therefore write code in a way which optimises for developers understanding and changing it, even at the expense of making it slower to run (within sensible limits etc etc).

I think this is hilarious when talking about someone like Muratori, who has had his hands in more games' code than most people on this site have ever even played. He is incredibly productive by comparison to all the people making excuses why their programs are slow bloated garbage fires.

Re: “Clean” code, horrible performance

#98

Most of those Clean code rules are BS. 1. Prefer polymorphism to “if/else” and “switch” - if anything, that makes code less readable, as it hides the dispatch targets. Switch/if is much more direct and explicit. And traditional OOP polymorphism like in C++ or Java makes the code extensible in one particular dimension (types) at the expense of making it non-extensible in another dimension (operations), so there is no…

I think if someone takes any of these typical guidelines - clean, SOLID, REST etc - and mindlessly applies it they’re likely to end up with a few parts of their applications which look weird, or perform poorly or end up being worse somehow. This is because there are inevitably going to be situations where the guidelines don’t fit well - they’re not necessarily hard and fast rules after all.

Any time you have these common rules of thumb in any part of your life you need to evaluate whether or not they are appropriate. But just because they’re not infallibly universal, doesn’t mean they’re wrong, it just means life throws complex situations at us sometimes, and that we need to be pragmatic and flexible

Re: “Clean” code, horrible performance

#99
post #64

Earlier quoted context omitted.

If you optimize for readability performance would suffer. If you optimize for performance readability will suffer. Casey prizes performance over everything else.

In this particular case I find the code optimized for speed (the one using switch) to be also more readable and simpler than the code using virtual dispatch. The problem with virtual calls in a big project is that there is no good way of knowing what is the target of the call, without some additional tooling like IDE. But in case of a switch/if, it is pretty obvious what the cases are.

I do agree. I've looked at code bases where the switch was replaced with virtuals and the like. It's kind of hard to navigate around the code when that happens. I think I'd usually rather have a completely separate path through the code rather than switch or virtual, making the decision at the highest level possible, usually the top-level caller.

Re: “Clean” code, horrible performance

#100

Most of those Clean code rules are BS. 1. Prefer polymorphism to “if/else” and “switch” - if anything, that makes code less readable, as it hides the dispatch targets. Switch/if is much more direct and explicit. And traditional OOP polymorphism like in C++ or Java makes the code extensible in one particular dimension (types) at the expense of making it non-extensible in another dimension (operations), so there is no…

In his small example he already added unforeseen couplings that could get out of hands if it was a big codebase. If you follow the principle "switch statements over [X]", try to add a new shape down the line and see how quickly you run into problems.

In the clean code version, your compiler will remind you to implement calculateArea, calculateNumberOfVertices, calculateWhatever, and so on and so forth.

With his version you have to add a new `case` to every switch statement and hope you didn't miss one with a default case, because the compiler won't catch it.

You don't need virtual functions and polymorphism to remove his switch statements. Just compose over inheritance.

Post reply on HN