Live data from Hacker News

“Clean” code, horrible performance

computerenhance.com

841–850 of 932 posts

Re: “Clean” code, horrible performance

#841

Earlier quoted context omitted.

> I'd pay good money to see a TV show where his style of programming ("spaghetti", as you claim) run laps around your "Clean Code". You'd like to pay money to be assured that you're right? I prefer to have an informed opinion based on actually trying stuff out and measuring†, I also find that as a result I don't feel the need to pay for validation. > For example, he wrote a terminal emulator in a weekend to prove tha…

> You'd like to pay money to be assured that you're right? I know I'm right, I'd pay money to see the embarrassment of the presumptuous Clean Code people who think that they can write maintainable code better than those who write software that matters (like Linux or Postgres, as mentioned before). > So, your thesis is that writing a terminal emulator - software which is pretending to be hardware that existed 40+ year…

> I know I'm right, I'd pay money to see the embarrassment of the presumptuous Clean Code people who think that they can write maintainable code better than those who write software that matters (like Linux or Postgres, as mentioned before).

You believe you're right, which of course you do, you almost can't help it.

Still, you keep mentioning Linux and it's worth a moment to consider that Linux actually does have the flavour of problem the Clean Code is modelling here, and it does indeed solve it the way Clean Code recommends and which Casey warns you will have egregiously bad performance. Several whole CPU cycles slower than Casey's spaghetti in fact.

Let's look more closely. In Casey's Clean example the Shape subclasses have to carry a table of functions to call to find out e.g. the area of that Shape, and then as we walk our array of Shapes we use these tables to call the appropriate area function. This costs us a dereference, which takes a few cycles.

With any luck, as this was described, your knowledge of how an OS works warmed up and you realised, "oh, that's, that's actually how the OS kernel works". Yup. Obviously Linux isn't written in C++ and so it has to actually hand-write the code to make tables of functions, so actually it's a bit clearer in the source, we can see that sure enough the implementation of CIFS for example and the implementation of XFS, and the implementation of FAT all just provide tables of functions.

So if Casey is right, shouldn't Linux be crushed by some 20x faster OS made by Casey or similarly minded games programmers (maybe Jonathan Blow) without these low performance tables ? Nope, there two good things to know here.

Firstly, this flexibility is immensely useful and it turns out most users can't live without it. A product which is 20x faster but can't do what you need is at best irrelevant, at worst a nuisance, a distraction. The demo shape project really needs to be able to be extended for arbitrary shapes.

Secondly, and this is often much more important in practice yet Casey just completely ignored it, this is a fixed cost overhead. Multiplying two numbers together is almost no work, so the overhead dwarfs the real work done, but in real software we are often doing a lot of work, yes even despite the "Single responsibility" rule and as a result the overhead is negligible in practice.

While we're in here it's important to notice that the overhead occurs because of the actual indirection, which was incurred in the C++ by the use of virtual function calls to several distinct types of Shape, and in our Linux kernel example by the use of several different filesystems via a table. You are not paying this overhead merely for the existence of functions to allow separation of concerns although that's what Casey implies.

> You're denying yourself very basic performance techniques if you close your eyes and pretend to not see the internals of each shape.

You're spending an unaffordable amount of your finite engineering resource on handling other people's problems in all of your code if you insist on peering inside everything as Casey does in this toy example.

The reminds me of the argument in Hare (another programming language from people who figure they're smarter than everyone else) that they shouldn't provide generics because you ought to build a custom data type each time you need something reflecting exactly what you needed each time. When I read that I decided to look briefly at how their compiler used a hashmap (IIRC) and of course it was buggy because it's all hand rolled and so it has a typical mistake you might make in your first attempt with a hashmap - as every hashmap in a Hare program is its own custom first attempt. I believe they subsequently fixed the bug after I reported it, so that's nice - until next time.

> He works on games, where you not only have to iterate very quickly but you also may need to completely change direction halfway through the project

Casey's only notable actual game project completed seems to have been The Witness, Jonathan Blow's second and more ambitious but arguably less successful game. Casey has worked in the games industry for a long time, but like Blow he's spent a lot more time telling other people he could do better than he has spent on actually demonstrating that.

In the time it took Jon and Casey to ship one game, John Carmack's id Software shipped Doom, some Doom sequels and Quake and some Quake sequels. Jon and Casey are not people to take your cues from if you want to have agile software development practices or ship products in a timely fashion.

Re: “Clean” code, horrible performance

#842
He’s basically showing data oriented design, where you, try to limit cpu cache misses by operating on the data.

This approach can be way faster, but is only relevant when you have a lot of entities you need to iterate over. If you have 3-100 objects it would of course still be faster but by negligible amount

Re: “Clean” code, horrible performance

#843

Earlier quoted context omitted.

> He does have a narrow view, but it does not make his claims invalid. I would tend to disagree on this, specially when claims come from the gamedev world. Games are presented as finished pieces (even when they aren't), and not just a release milestone. Ideally, a game is a one-off effort where you write a piece of code and if you're lucky, you won't have to touch it again. So, doing one-off optimizations instead of…

> Two cpu generations later, the Pentium comes out, and both mul and div take 1 clock cycle. Where are you getting this information? Agner[0] lists DIV as taking 17 cycles at best (8-bit operand already in a register) on the P5, and MUL as taking 11 cycles. Even Tiger Lake takes 6 cycles for DIV. There are ways [1] to beat that, but I don't think you can get it down to a single cycle. [0]: https://www.agner.org/optim…

You are completely right, I just had a major brain fart. I probably mixed up some things (or had some bad/incomplete source at the time). More than two decades have passed, so its probably me with wires crossed.

Re: “Clean” code, horrible performance

#844

Earlier quoted context omitted.

> He does have a narrow view, but it does not make his claims invalid. I would tend to disagree on this, specially when claims come from the gamedev world. Games are presented as finished pieces (even when they aren't), and not just a release milestone. Ideally, a game is a one-off effort where you write a piece of code and if you're lucky, you won't have to touch it again. So, doing one-off optimizations instead of…

"Games are presented as finished pieces" is an idea that's at least a decade out of date. The industry has gone very hard on the idea of Games as a Service and it's now normal for AAA games to receive years of content updates.

From a software perspective, they are. Most games don't change requirements (or base code) during their maintenance releases, as these releases may fix some code bugs, more often than not provide only incremental updates on content. Compare that with eg. intermediate releases of software like OpenOffice.

Re: “Clean” code, horrible performance

#845

Earlier quoted context omitted.

> The thing that sets him off is that he is using a computer with enormous computing power and everything is slow. If that's his complaint, then "clean code" isn't the problem. The problem is capitalism and/or human nature. Once something performs acceptably well, ie good enough to sell it, performance isn't going to get any better. Flashy stuff and features get you money, going from 400ms to 100ms gets you...nothing…

> going from 400ms to 100ms gets you...nothing. According to Amazon [0] that'd be a 3% gain in sales (assuming the inverse holds true as getting slower, anyway). [0] https://www.gigaspaces.com/blog/amazon-found-every-100ms-of-...

That's if it's in your sales flow, not if it's in your software.

Re: “Clean” code, horrible performance

#846

Earlier quoted context omitted.

> He does have a narrow view, but it does not make his claims invalid. I would tend to disagree on this, specially when claims come from the gamedev world. Games are presented as finished pieces (even when they aren't), and not just a release milestone. Ideally, a game is a one-off effort where you write a piece of code and if you're lucky, you won't have to touch it again. So, doing one-off optimizations instead of…

> “Ideally, a game is a one-off effort where you write a piece of code and if you're lucky, you won't have to touch it again.” Ideally a game pulls in over a billion dollars per year, every year for over a decade. Think World of Warcraft or Fortnite , not Flappy Bird.

And the amount of money changes the fact that the core engines are written as a one-off effort how, exactly? Updates to the scripting engine to fix play-ability issues and content updates aren't really heavy software refactoring. Sure, there are usually some actual code bugfixes on the initial releases - and more often than not - related to someone implement some really clever trick that raises an exception on some cpu. Its not like they are incrementally rewriting and extending the internal engine for a decade, as it happens eg. with a browser.

Re: “Clean” code, horrible performance

#847

Earlier quoted context omitted.

The thing that sets him off is that he is using a computer with enormous computing power and everything is slow. He does have a narrow view, but it does not make his claims invalid. I liked that his POC terminal made in anger made the Windows Terminal faster. But even in that context it was clear that by making some tradeoffs - which the Windows Terminal team can not make (99.99% of users do not run into the issue, b…

But how much of that slowness is due to code that values "cleanliness" excessively? I bet that if you look at the source of nearly any application on your PC, it will be very much not clean on average.

[deleted]

Re: “Clean” code, horrible performance

#848
post #215

> Our job is to write programs that run well on the hardware that we are given. The author seems to be neglecting the fact that the whole point of “clean code” is to improve the likelihood of achieving the first goal (code that runs well, i.e. correctly) across months/years of changing requirements and new maintainers. No one (that I’ve ever spoken to or worked with, at least) is under any illusions that you can almo…

> The author seems to be neglecting the fact that the whole point of “clean code” is to improve the likelihood of achieving the first goal (code that runs well, i.e. correctly) across months/years of changing requirements and new maintainers. Yes that is the whole point of "clean code". Thing, is, it failed. Simplicity is better achieved with other methods. Forget Uncle Bob and SOLID, read John Ousterhout (A Philosop…

I'm certainly not going to defend Uncle Bob here, but I don't think you have to be a SOLID cultist to think that preferring smaller functions, factoring out oft-repeated patterns, and relying on a language's abstraction features (e.g. polymorphism) are useful heuristics for managing complexity and maintainability in a codebase. Like, the article's author complains at length about the overhead of a virtual function call over a switch statement; I don't think their critique is really focused on the nuanced differences between the various schools of "how to make your code nicer to read" (at least, I didn't read it that way).

That being said, A Philosophy of Software Design looks like a good read. Thanks for the recommendation.

Re: “Clean” code, horrible performance

#849
post #802
post #6

Unrelated to the content itself, am I the only one wondering if he has his t-shirt mirrored or if he's really skilled at writing right-to-left? Content wise: his examples show such increases because they're extremely tight and CPU-bound loops. Not exactly surprising. While there will be gains in in larger/more complex software by throwing away some maintainability practices (I don't like the term "clean code"), they…

>Just toss a 0.01ms I/O operation in those loops; it will throw the numbers off by a large margin, then one would just rather pick sanity over the speed gains without blinking. I mean, yes, if you do something completely fucking idiotic like put an IO operation inside a tight calculation loop, then all your speed gains will vanish. But I don't see how that refutes anything.

I said I/O, but it could be memory access. All he does fits in registers and maybe cache. Also, 0.01ms was the normal RAM latency when I started using computers...

Do you remember the last time you had to do a tight calculation loop, and not only that, but one that significantly impacted the total runtime? Personally I do, it was roughly 15 years ago writing a raytracer.

I can imagine that happening in game/3D dev, DSP, emulators, ML, and maybe some other types of software, but even in those cases one already has dedicated libraries and hardware to extract the performance from where it can be extracted.

I mean, Python is slow as an old dog, yet it gets most of the ML fun.

Re: “Clean” code, horrible performance

#850
post #837

Earlier quoted context omitted.

Yes, he is a good example. His games are as highly regarded as they are because he takes the time to really work through everything about them and ensure they're the product he wants. If you watch his streams you'll see that he is constantly experimenting with things, both gameplay-wise and in the engine... and now in his own compiler for his own programming language. Jon is not making the by-the-numbers annual entry…

Look I'm a huge fan of his games! And I really can't understate how influential his game design nor the work he does for the indie community. However, I think a lot of folks tend to assume his software engineering skills are great because his game design is excellent. I don't think that's an earned position. Releasing 2 games in 18 years that are not pushing the technical envelope does not scream software engineering…

> I don't think that's an earned position.

I disagree.

> You say he has more credits but only one of those is programming since Braid.

He did start a company after that you know. A successful one that makes money and employs people to make art. I don't imagine that running a business takes no time from his life.

> But even at the time Braid could have been written in python SDL wrappers and probably had similar performance

Braid did a lot more than you give it credit for. Here's a GDC talk about the rewind system in which he explains some of the hurdles he had to deal with: https://www.youtube.com/watch?v=8dinUbg2h70&t=5s Pay particular attention to the discussion of the background particles and how to get that to work within the RAM constraints.

> On the other hand, on a software engineering level those paint by numbers Modern Warfare and FIFA games are both more technically impressive and are designed for fast iteration

Hardly anything about these games change from release to release. They're not exploring new gameplay problem spaces, they're not doing anything super interesting or surprising on a technical level either and I don't get why you think they are. Of course if you keep using essentially the same engine and know exactly what you're trying to make, making another like a goddamned factory is going to happen quicker than if you're trying to make something unique and meaningful.

> If clean code is about maintenance and time to market, the Blow paradigm hasn't proven that its needed or fixes the holes in clean code.

I have heard "maintenance and scaling" as an excuse for poorly performing software for a long time now, yet what I'm not seeing is software that has features added on quick schedules and without bugs. So at best I'd say that it isn't accomplishing what it is supposed to and, at the same time, it is wasting our time and resources by producing slow software to boot.

Post reply on HN