跪拜 Guibai
← All articles
Backend

Clean Code Rules Can Cost You 15x in Runtime Performance

By 皮皮林551 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

A 15x slowdown is equivalent to throwing away over a decade of CPU advances. For any system where throughput or latency matters—games, databases, trading, embedded devices—blindly following clean-code dogma can become the single largest performance tax in a codebase.

Summary

A benchmark using the classic shape-class hierarchy—polymorphism, tiny functions, no internal knowledge—required 35 cycles per area calculation. Replacing the virtual calls with a switch statement over a flat struct immediately cut that to 24 cycles. Fusing the data and operation into a single table-driven function dropped the cost to 3.0–3.5 cycles, a 10x improvement over the original clean version.

When the problem was extended to a corner-weighted area sum, the gap widened further. The clean OOP version ran 15 times slower than the table-driven approach. An AVX-accelerated variant stretched the difference to 20–25x.

The core issue is that clean-code practices hide intent behind virtual dispatch and separate translation units, starving the compiler of optimization opportunities. Organizing code by operation rather than by type exposes patterns that let compilers and CPUs work together efficiently.

Takeaways
Polymorphism and virtual dispatch on a shape hierarchy cost 35 cycles per area calculation; a flat struct with a switch statement cut that to 24 cycles.
Fusing data and operation into a table-driven function reduced the cost to 3.0–3.5 cycles, a 10x speedup over the clean OOP version.
Adding a second property (corner count) widened the gap: the clean version ran 15x slower than the table-driven version, and 20–25x slower with AVX optimizations.
Clean-code rules hide intent behind virtual calls and separate translation units, preventing the compiler from optimizing effectively.
Organizing code by operation rather than by type makes common patterns visible and enables drastic simplifications.
The DRY principle was the only clean-code rule that did not inherently degrade performance in these benchmarks.
Conclusions

The benchmark uses the clean-code advocates' own textbook example, so the performance penalty is not a strawman—it is baked into the canonical illustration of the paradigm.

The slowdown compounds as object complexity grows: more properties mean more virtual calls and more indirection, widening the gap between clean and data-oriented designs.

Compiler optimizers are effectively neutralized by class hierarchies because the actual code being executed is hidden behind runtime dispatch, making inlining and vectorization impossible.

Switching from a type-first to an operation-first mental model is what unlocked the 10x speedup, suggesting that the axis of decomposition is a first-order performance decision.

Many developers never see these bottlenecks because their applications are IO-bound, but the cost is still paid in battery life, cloud compute bills, and latency tail percentiles.

Concepts & terms
Virtual dispatch (vtable)
A mechanism in C++ where calling a virtual function requires an indirect lookup through a virtual function table (vtable) at runtime, preventing the compiler from inlining the call or knowing which code will execute.
Data-oriented design
An approach that organizes code around data layout and transformation rather than around objects and inheritance, aiming to keep data contiguous and operations predictable for CPUs and compilers.
Table-driven method
Replacing conditional logic (switch/if-else) with a lookup table that maps input values to coefficients or function pointers, reducing branch mispredictions and enabling vectorization.
Loop unrolling
A manual or compiler optimization that replicates the loop body multiple times to reduce loop overhead and expose more instruction-level parallelism.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗