C++ Logo


Advanced search

Re: "Clean" Code, Horrible Performance

From: Florian Sattler <sattlerf_at_[hidden]>
Date: Tue, 7 Mar 2023 09:35:59 +0100
I don't want to add on much more, as a lot was already. I just have two
small nits.

Does anyone have/know where to find his measurement setup (compiler,
cxx_flags, etc.) + code? I found it odd that he did not post/show how
his measurement setup is or his full code. We all know that, especially
for smaller benchmarks/micro benchmarks a few mistakes can make a large
difference (see Chandlers CppCon Talk from 2017: "Going Nowhere
Faster"). So, I wanted to peak into the setup but could not find anything :(

However, what bothered me the most in his reasoning, was his selection
of a "representative" baseline. As far as I understood, he just picked
the example from a book (prob. the clean code one)? When have book
examples, focused on explaining coding styles, ever been optimized with
regard to performance? I don't want to go into whether clean code is
good or not, but selecting this as a baseline is highly misleading. In
the CC "group" he selects a book example, in the NonCC group he spends
time to optimize and reason about the specific problem. This begs the
question, isn't there maybe a potential member of the CC group that
would have done better? Maybe not faster, maybe not even 1:1, but closer
with a different perf. tradeoff.

Just as an example:
f32 TotalAreaVTBtr(std::span<shape_base *> Shapes) {
     return std::transform_reduce(Shapes.begin(), Shapes.end(), 0.0f,
                                  [](shape_base *obj) { return
obj->Area(); });

Clean? Worse? Better? sadly, I don't now ;)


On 3/1/23 15:02, Arthur O'Dwyer via SG20 wrote:
> On Wed, Mar 1, 2023 at 7:42 AM Kate Gregory via SG20 <sg20_at_lists.isocpp.org>
> 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-07 08:36:17