views:

848

answers:

19

I am currently working for a client who are petrified of changing lousy un-testable and un-maintainable code because of "performance reasons". It is clear that there are many misconceptions running rife and reasons are not understood, but merely followed with blind faith.

One such anti-pattern I have come across is the need to mark as many classes as possible as sealed internal...

*RE-Edit: I see marking everything as sealed internal (in C#) as a premature optimisation.*

I am wondering what are some of the other performance anti-patterns people may be aware of or come across?

+14  A: 

Variable re-use.

I used to do this all the time figuring I was saving a few cycles on the declaration and lowering memory footprint. These savings were of minuscule value compared with how unruly it made the code to debug, especially if I ended up moving a code block around and the assumptions about starting values changed.

Kev
and any compiler worth it's salt will use the same memory location or register for both the two variables as it would if you reused one (because their lifetimes obviously don't overlap).
rmeador
Exactly. Plus if you're using a non-compiled language, the overhead of the language itself probably outweighs the benefit again. But who knows? Sebastian's answer is the only way to find out. :)
Kev
+4  A: 

Lack of clear program structure is the biggest code-sin of them all. Convoluted logic that is believed to be fast almost never is.

krosenvold
+54  A: 

The biggest performance anti-pattern I have come across is:

  • Not measuring performance before and after the changes.

Collecting performance data will show if a certain technique was successful or not. Not doing so will result in pretty useless activities, because someone has the "feeling" of increased performance when nothing at all has changed.

Sebastian Dietz
I'd vote this up twice if I could. Good call.
Kev
Yes, this is a great point!!
Xian
I have only one vote-up to give for this post.
David Thornley
Essentially the root of all performance cargo cults.
Jon Ericson
+6  A: 

Premature performance optimizations comes to mind. I tend to avoid performance optimizations at all costs and when I decide I do need them I pass the issue around to my collegues several rounds trying to make sure we put the obfu... eh optimization in the right place.

PEZ
-1 You "tend to avoid performance optimization at all costs"? That seems to be a bit extreme, Also you seem to equate unreadable code with optimized this not true. Even though it is correct that premature optimization is bad but the rest of your answer had nothing to do with the your heading.
hhafez
I don't really buy the "premature optimization is the root of all evil" thing. I think that the real issue is that you should focus optimisation only on things that need it; it's easy to get bogged down in optimising routines that really won't matter in the scheme of things because they are seldom called, or they don't really make much difference. But it is still very important to think about the performance of your code when you design its overall architecture, where it could make difference.
thomasrutter
+2  A: 

Exploiting your programming language. Things like using exception handling instead of if/else just because in PLSnakish 1.4 it's faster. Guess what? Chances are it's not faster at all and that two years from now someone maintaining your code will get really angry with you because you obfuscated the code and made it run much slower, because in PLSnakish 1.8 the language maintainers fixed the problem and now if/else is 10 times faster than using exception handling tricks. Work with your programming language and framework! I call it Pooh Coding.

PEZ
+1  A: 

I believe it is a common myth that super lean code "close to the metal" is more performant than an elegant domain model.

This was apparently de-bunked by the creator/lead developer of DirectX, who re-wrote the c++ version in C# with massive improvements. [source required]

Xian
I have read articles both agreeing and opposing your statement. Can you fill in the [source required]?
borisCallens
Yeah I was hoping, the collective group may be able to help me out here.. I am searching on google for the link, I will edit this post as soon as I find it.
Xian
+2  A: 

General solutions.

Just because a given pattern/technology performs better in one circumstance does not mean it does in another.

StringBuilder overuse in .Net is a frequent example of this one.

annakata
True that. Luckely there are currently as much articles about the performance of all the string techniques as there are ppl misusing them.
borisCallens
sadly plenty of people who aren't familiar and that was just one common example. The reverse while loop is another example - sometimes reversing an array matters :)
annakata
+23  A: 

The elephant in the room: Focusing on implementation-level micro-optimization instead of on better algorithms.

dsimcha
...or better architecture.
Darron
+1  A: 

Appending to an array using (for example) push_back() in C++ STL, ~= in D, etc. when you know how big the array is supposed to be ahead of time and can pre-allocate it.

dsimcha
the amortised performance (NlogN) isn't *too bad in this case...
Jimmy
Appending to arrays is amortized O(1), but with a *MUCH* larger constant term than allocating once and then filling.
dsimcha
+1  A: 

You could be interested in this Jeff's article

Rulas
+1  A: 

Not my original quote, of course, but there are two rules for optimizing performance.

  1. Don't do it.
  2. (experts only) Don't do it yet.

If people are worried about performance, tell 'em to make it real - what is good performance and how do you test for it? Then if your code doesn't perform up to their standards, at least it's something the code writer and the application user agree on.

If people are worried about non-performance costs of rewriting ossified code (for example, the time sink) then present your estimates and demonstrate that it can be done in the schedule. Assuming it can.

Glazius
+4  A: 

One that I've run into was throwing hardware at seriously broken code, in an attempt to make it fast enough, sort of the converse of Jeff Atwood's article mentioned in Rulas' comment. I'm not talking about the difference between speeding up a sort that uses a basic, correct algorithm by running it on faster hardware vs. using an optimized algorithm. I'm talking about using a not obviously correct home brewed O(n^3) algorithm when a O(n log n) algorithm is in the standard library. There's also things like hand coding routines because the programmer doesn't know what's in the standard library. That one's very frustrating.

Rob K
or throwing hardware at a badly designed database rather than redesigning it.
HLGEM
I saw that happen too.
Rob K
+2  A: 

Changing more than one variable at a time. This drives me absolutely bonkers! How can you determine the impact of a change on a system when more than one thing's been changed?

Related to this, making changes that are not warranted by observations. Why add faster/more CPUs if the process isn't CPU bound?

Patrick Cuff
This is really important! If you test multiple changes at once and get an improvement, which of those changes caused the improvement? What if one of those changes actually harmed performance a bit but that was masked by a performance boost in another change? You could be leaving CPU cycles on the table. :)
thomasrutter
+2  A: 

Do not refactor or optimize while writing your code. It is extremely important not to try to optimize your code before you finish it.

Qubeuc
+1  A: 

Some developers believe a fast-but-incorrect solution is sometimes preferable to a slow-but-correct one. So they will ignore various boundary conditions or situations that will "never happen."

This is never a good idea. Solutions always need to be "correct", but you may need to change your definition of "correct" depending upon the situation. What is important is that you know what you want the result to be for any condition, and that the code gives those results.

Kristopher Johnson
+4  A: 

Using design patterns just to have them used.

m0rb
+3  A: 
  1. Using #defines instead of functions to avoid the penalty of a function call. I've seen code where expansions of defines turned out to generate huge and really slow code. Of course it was impossible to debug as well. Inline functions is the way to do this, but they should be used with care as well.

  2. I've seen code where independent tests has been converted into bits in a word that can be used in a switch statement. Switch can be really fast, but when people turn a series of independent tests into a bitmask and starts writing some 256 optimized special cases they'd better have a very good benchmark proving that this gives a performance gain. It's really a pain from maintenance point of view and treating the different tests independently makes the code much smaller which is also important for performance.

Laserallan
+3  A: 

Julian Birch once told me:

"Yes but how many years of running the application does it actually take to make up for the time spent by developers doing it?"

He was referring to the cumulative amount of time saved during each transaction by an optimisation that would take a given amount of time to implement.

Wise words from the old sage... I often think of this advice when considering doing a funky optimisation. You can extend the same notion a little further by considering how much developer time is being spent dealing with the code in its present state versus how much time is saved by the users. You could even weight the time by hourly rate of the developer versus the user if you wanted.

Of course, sometimes its impossible to measure, for example, if an e-commerce application takes 1 second longer to respond you will loose some small % money from users getting bored during that 1 second. To make up that one second you need to implement and maintain optimised code. The optimisation impacts gross profit positively, and net profit negatively, so its much harder to balance. You could try - with good stats.

Simon Gibbs
Yeah one of those ironic catch 22's where you need the traffic in the first place to get the stats, and it could be those same very problems that prevent their collection...
Xian
You don't need traffic to measure the cost of making a change. You could collect that from your team, from SVN logs, or perhaps from tools like Mylyn (which tells me I've spent 1h 37m over engineering data structures about towns within geographic regions, speaking of which... )
Simon Gibbs
+1  A: 

Once I had a former client call me asking for any advice I had on speeding up their apps.

He seemed to expect me to say things like "check X, then check Y, then check Z", in other words, to provide expert guesses.

I replied that you have to diagnose the problem. My guesses might be wrong less often than someone else's, but they would still be wrong, and therefore disappointing.

I don't think he understood.

Mike Dunlavey