C++ Logo

sg20

Advanced search

Re: "Clean" Code, Horrible Performance

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Wed, 1 Mar 2023 09:02:20 -0500
On Wed, Mar 1, 2023 at 7:42 AM Kate Gregory via SG20 <sg20_at_[hidden]>
wrote:

> Part of the issue here is that we have normalized so much of this
> decades-old advice that the comparisons are not what they once were.
>
>
>
> Take a simpler piece of advice like declaring things immediately before
> you use them, or at least closer to where you use them. I’ve had arguments
> and pushback on this from people who are writing functions that are at most
> 20 lines long. When I tell them about 5000 line functions they just can’t
> believe me. And the worst of those functions that were thousands of lines
> long always seemed to have a giant switch, with each case screens and
> screens long, or nested loops again screens and screens long.
>

+1.

Also, notice what the presenter says @21:30: These ("clean code") rules
were designed to produce more maintainable codebases. So naturally they'll
tend to produce less performant codebases — that's just the nature of
"pick-two triangles." Every time you hear "I'm optimizing for X," you
should understand that it means "I'm pessimizing for Y and Z."

In this particular context, I'd say the relevant triangle is
1. Abstraction (clarity of high-level)
2. Understandability (clarity of low-level)
3. Performance
where the particular "Clean Code" style he's targeting is clearly
optimizing for 1 and 2 together (and thus, not even a little bit of 3).
I'm sure we all know programmers (many of them on the committee) who enjoy
targeting 1 and 3 together (and thus, not even a little bit of 2) — in the
context of this example, it'd be someone who writes a vectorized algorithms
library to replace that 4x-unrolled `for` loop.
The presenter's optimizations in this talk are focused mainly on giving up
1 to achieve better 3 (while leaving 2 only a little worse off, IMHO).

In big industrial codebases, 1 and 2 are really important, and 3 tends to
be deprecated in practice. Cynically, one might say that that's because 1
and 2 operate on the labor side — they reduce the *difficulty of the
worker's job* — and 3 operates on the capital side — it increases the *value
to the employer* of the finished product. So naturally when you (A)
distinguish the worker from the employer and (B) give the worker free rein
to optimize 1+2+3 in any way they see fit, well, they'll improve 1 and 2
and decrease 3, every time.

This also explains the existence of "10x programmers," in the sense of a
programmer who's 10x better than their peers at whatever metric you happen
to care most about. As this presentation shows, it's very very easy to get
a 10x or even 20x improvement in one metric by completely discarding
another. If your boss values the improved metric while not knowing about
the discarded one(s), then he'll see you as a "10x" or "20x" programmer, by
definition.

Of course *every feature is a tool*, and as a tool, it should be used for
its intended purpose. If you're using polymorphism and not reaping the
benefits of polymorphism (open hierarchy, understandability, abstraction),
then you're reaping only the costs. If you're writing 10-line functions and
not reaping the benefits of 10-line functions (understandability,
testability), then you're reaping only the costs. Reap enough costs without
any matching benefits, and your code *can* get worse on all three metrics
simultaneously without getting better at any of them.

my $.02,
–Arthur

Received on 2023-03-01 14:02:34