CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Karl Seguin

.NET From Ottawa, Ontario - http://twitter.com/karlseguin/

Good Programmers Micro Optimize

Programming is too delicate a task to heavily rely on generalisms. Even at the relatively high level of programming we do, what works in one situation isn’t guaranteed to work in another. As developers we typically lack the imagination necessary to foresee even a fraction of how real users will use our systems. This combination makes it dangerous to rely on anything but firsthand experience.

Good developers must pursue their intuition and satisfy their curiosity by means of continuous experimentation. Sadly, too many developers look down on micro optimization, ensuring that curious developers never ask their performance question for fear of being ridiculed (I found a couple of newsgroup posts from years ago where someone asked about string to integer conversion and I arrogantly shot them down for asking such an insignificant question). It’s rather silly that on the one hand we fear leaky abstractions is getting the best of our community, and on the other we look down at attempts to gain greater understanding.

The most cited reason against micro optimization is that clarity/maintainability/readability should trump any minor performance gains. That implies that the two concepts are mutually exclusive – which may be true in some cases, but in other cases isn’t at all (such as generics). And, much like you can’t know if something is a micro (or a macro) optimization until you try, there’s a good chance you can’t really tell the impact on maintainability until you let your creativity loose.

Back to my point about generalities, and we can see how easy it is for someone not to have to try it out for themselves. There are countless blogs that praise StringBuilders as the fastest way to concatenate a string – which is true except for when it isn’t – and even more blogs that praise the superior performance of stored procedures – which is also true except when it isn’t. Blogs and bloggers aren’t to blame though. In the end, developers who sheepishly follow, perhaps because others have shamed them into not asking, are responsible for their own enlightenment.

I also want to point out that when it comes to both micro optimization and premature optimization, unit tests should play a significant role in your experimentations. Properly written unit tests will ensure that an optimized version works within the same parameters as the original. TDD should embrace an addition to their red/green/refactor motto --> red/green/optimize/refactor.

If you don’t optimize early and often, you’ll never understand the value and cost of those optimizations. All you’ll have to go by are general statements made by others, rather than an actual understanding of what’s happening beneath the compiler.

While the Alpha Geeks are off mastering Ruby, I think I might spend some spare cycles trying to familiarize myself with MSIL.
 



Comments

FransBouma said:

Micro-optimization is a slippery slope, THAT's why it's so stupid to do: where will you draw the line? Perhaps writing EVERYTHING in hand-optimized assembler is faster! :) I think if you write everything not in a .net language but in hand-optimized x86 asm it might be faster, don't you think? ;)

Do you see the sillyness in this? What you should do is look for a better algorithm. That's what brings performance on the table. Optimizing searching a string is a good example. Say you start with the first character and so on... is that fast? No, there are faster algo's than that. However if you use the slow algo, optimize the crap out of your code, you still will be beaten by a slow implementation of a much faster algo.

Sure, the code you write shouldn't be unnecessarily slow, however the focus shouldn't be on that. So if you think you need MSIL statements... you really are on the wrong track.

# August 10, 2007 4:42 AM

karl said:

Sure it's dangerous, but developers need to achieve a balance. If we always just listened to the man, no one would be using o/r mappers.

To me, this is (like most things) comes down to discipline. First you need to recognize that you even have the time to explore a [potentially useless] alternative. Next you need to be diligent about whether or not it should be implemented. Finally, you need to mentally catalog your findings for next time.

I don't plan on writing MSIL statements, but I do think understanding it could come in quite handy. This is along the same point as Spolsky saying developers ought to know C (which I fully agree with).

# August 10, 2007 8:04 AM

Joe said:

But i thought the cool kids were all "avoid premature optimization"....?

# August 10, 2007 9:14 AM

Greg said:

I would spend the time learning the JIT/CLR as opposed to IL if you want to learn about micro-optimizations, the JIT optimizes away alot of stuff that you may think as bad looking at IL...

That and a spend time with reflector looking at the framework classes. A perfect example of a the benefit herewould be to prefer a LinkedList<T> over a List<T> when you are adding and removing alot of nodes in a large list.

To be honest I find that micro-optimizations should only be applied to about 10% of code.

# August 10, 2007 5:04 PM

BennyXNO said:

Why should you optimize before you know that your code is slow?

If your code is designet well and you have test for everything, you can optimize things after you have run your load tests.

The need for optimizing is maybe not there even if your think so, maybe you should approach the problem from a different angel. Is there some way that you can make a user become happy with your slow code?

The need for optimizing should be driven by your application type. A game that needs fps needs optimizing, no doubt about that. A forms or web application seems not to be the biggest candidates for optimization.

Why waste time on optimization when you can give your customers hard needed functionality

# August 11, 2007 6:05 PM

karl said:

Benny:

You should optimize, not for the sake of optimizing, but for the sake of learning. As the years roll on and managed languages assert themselves almost fully, important knowledge is being lost.

I don't think people should use foreach loops instead of for loops, but I DO think they should understand the difference. Maybe not down to the IL, but at least enough to establish a foundation.

>>"Why waste time on optimization when you can give your customers hard needed functionality"

I think that sums up our difference in opinion. Your right if you just seem optimization as a means to improve performance and it isn't at all necessary. However, I honestly believe optimizations, whether they are necessary or not, are one of the few opportunities in the managed world to get somewhat close to the machine. Languages are very far away from making that a waste of time.

Your last point is really where you and I don't see ei

# August 11, 2007 7:40 PM

Peter Ritchie said:

One of my gripes is the misquoting of Hoare being used as an excuse to write slow code.   The entire quote is "We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil.".  This means you still have to check to see if optimization is needed to ensure the code isn't in that magic 3% that does need optimization.

My gripe  is that you should choose the most efficient algorithm for the task at hand, and that's not a premature optimization--despite that many people would claim it's a premature optimization.  The time it takes to write code that concatenates strings with the + operator and the time it takes to write code that uses StringBuilder is the same.  When you choose StringBuilder over operator+ you're not prematurely optimizing.  Changing operator+ to use StringBuilder would be considered premature optimization.

But yes, you have to run performance tests from time to time when performance is at issue; which means you have to micro optimize from time to time.

# August 13, 2007 3:08 PM

Evan said:

At first, I started to have a gut reaction against what you were saying.  Usually this is because those micro-optimizations come in the form of brittle, procedural code.  Later in your post, you jumped into unit testing and TDD.

Generally speaking, if you can do microoptimizations in a test-driven fashion, I'm quite ok with them.  The fact that they are test driven with OOP principles in mind should ensure their maintainability (assuming that's done well).

The knee-jerk reaction a lot of us have is from seeing the "optimized" procedural code we've seen in the past, where you end up having to rewrite it all when you change it (and the optimization was never really needed in the first place).

My preferred method of working, however, is different.  I'd rather write the simplest thing that works for now (passes my user story and makes my tests green) and then watch the unit test execution time and integration tests to determine what actually needs deeper attention.

# August 21, 2007 12:03 PM

karl said:

Evan,

Thanks for keeping an open mind and reading it all the way through :)

We're actually going through a round of performance testing and optimizing, and the unit tests are providing the team with an unbelievable amount of confidence that changes made won't break any business rules.

# August 21, 2007 10:23 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add
Check out Devlicio.us!

Our Sponsors

Free Tech Publications