DEV Community

Arne Mertz
Arne Mertz

Posted on

Simple and Clean Code vs. Performance

This article was originally published on my personal blog "Simplify C++!". In almost three years and ~140 posts, it is the most discussed and most visited post I have ever written. Simplify C++! is a blog about modern C++ and Clean Code.

One of C++'s strengths is that it is possible to write very performant code. But does that mean we always have to worry about performance and write our everyday code as performant as possible? Should we give up simplicity for performance? Do we have to?

I don't think so

There are many reasons why I don't think we should sacrifice simple and clean code to write more performant code per se. In contrary, I have been criticized for advocating the sacrifice of performance for simplicity.

I would prefer if everyone wrote simple and clean code by default. OK, that's pretty obvious, because that's what my blog is all about. Â But what about reasons why I think so? Here are some.

Performance is not efficiency

There is an important point to get out of the way first. We have to distinguish between efficiency and performance. What is the difference? In very simple terms it is how fast you do something (performance) vs. how long it takes to do it (efficiency).

At a first glance that might sound like it's the same, but it's not. Imagine you have to go from point A to point B. Efficiency means you go the shortest way. Performance means you run instead of walking. So if you run as fast as you can around the whole block to get to your neighbor, you are at high performance, but not very efficient.

In programming, loops often contribute much to program run time. Here, performance would mean that a single loop cycle executes faster. Efficiency means that you have to do fewer cycles, mostly because you have a smarter algorithm.

Sometimes you can not have the best of both worlds. The steps of a more efficient algorithm may be less performant. However, before you try to squeeze the last bit of performance out of a piece of code, make sure it is efficient. Only if you have tested all possibilities in terms of efficiency it can pay off to worry about performance.

Sometimes it is enough to make your code more efficient to get the desired speed without having to worry about performance details.

We don't need performance everywhere

This one is obvious, but many programmers, especially new programmers, tend to overlook it. There are tons of questions on forums and StackOverflow, asking about how a certain piece of code can be optimized. When one asks the counter question if the code is really a performance bottleneck it most often turns out that it is not.

There is a saying that 80% of the runtime of a program is spent in only 20% of the code. Some say it's 90/10. The exact numbers are not very important in general. The crucial point is that the program spends a lot of time in a small amount of code.

On the other hand, that means that most code does not contribute much to the total run time, and if we optimize the hell out of it we won't see much of a result if we see anything at all.

Don't optimize code that you have not proven to be vital for the overall program performance.

We don't really know how to write performant code

I know, how can I dare to say something like that. The fact is that one of the major contributions to program runtime is the number of instructions the processor has to execute. And those are not written by us, but by the compiler and its optimizer.

Optimizers come in all shapes and colors, and unless you are an expert in the field, you can't even guess what they will do to a nontrivial piece of code. Optimizers can eliminate temporary objects, they can inline functions, sometimes even at link time, and they can shuffle around and eliminate lots of those instructions.

So, with those superpowers in the machine and our complete ignorance of what code will give the best result, what can we do to make our code more performant? At first, nothing. And if we really have to care about performance, we can not rely on our imagination or experience, we have to use a tool.

By default, write code for maintainability, because it might be as performant as anything else. If you really have to improve performance, use a profiler.

Of course, this does not mean you should prematurely pessimize. If there are two or more ways to write a piece of code that are equally readable, use the way that will probably give the best performance. For example, use ++iter instead of iter++ if you don't save the result of the expression, and so on.

Performance and simplicity don't always contradict each other

The other major contribution to program run time, maybe even more than the number of instructions, is the layout and structure of data in memory. There is a great talk about getting better performance by using the right data structures by Chandler Carruth, so I won't go further into this.

All I want to say is, if the memory layout of your data is bad, much of the runtime goes into the fetching of data from memory and saving a few instructions won't have as much of an impact as using the right data structures.

Make sure you use the most performant data structures before you start tweaking your code for more performance.

There is another point to writing performant and simple code: Using the libraries you have, and using them right. Those library writers usually are smart guys and know how to write performant code. They particularly know how to use their profilers.

So if you use libraries instead of rolling your own solutions, your code is likely to be not only more robust and simple to maintain, but also to be more performant.

Know and use your libraries, unless your profiler showed them to have bad performance.

Conclusion

Write readable and simple code by default. If you actually have a performance problem and have located it, there are still many options that are more promising than turning your code into a fast but unreadable mess. Sacrifice simplicity for performance only as a last resort, and always use a profiler when you are dealing with performance problems.

Latest comments (4)

Collapse
 
mortoray profile image
edA‑qa mort‑ora‑y

I agree. I've done a lot of optimizations, in places that really needed it, and some places that didn't. The first order of attack is always efficiency. Then you look at memory usage.

If that doesn't fix the issue, then you go get lunch, dinner, go on vacation, reevaluate life choices, then learn how to profile code. The learn how to research and make sure the efficiency part is right. Then read about memory and check if that is the best use.

When all else fails you resort to actual optimization.

Of course many optimizations are simple cleanups and can be done without too much thinking. But you'll only know that once you've learned how to profile and identify such issues.

Collapse
 
tamasrev profile image
Tamas Rev

There are so many people I'd like to read this post. Instead, I'll post it to twitter.

Collapse
 
2xdeveloper profile image
Bartosz Borowik

"The cleaner and nicer the program, the faster it's going to run. And if it doesn't, it'll be easy to make it fast." - Joshua Bloch

Collapse
 
kevinrstone711 profile image
Kevin R Stone

1 way to kill your code base quickly is by prematurely optimizing. Save it as a last resort when you really need it. Adequate, but clean is better than optimized and ugly.