I’ve been having a lot of fun playing with code lately. One of the things I have been experimenting with is cryptography (See Tiny Book of Simple Cryptography) For one project I wanted to create a string of ones and zeros to represent the binary value of letters. I quickly came up with three ways of doing this. I know that are probably many more ways than that. But for now I have some that work and one of them I really like.
Which one is best? Well, that depends. Which one is the fastest? That depends as well. I think I know which one is fastest. It uses the bitwise & operation which generally is pretty quick. One used the Math.Pow function which I suspect slows things down quite a bit. The third uses nothing fancy at all and could easily be coded by someone with only a little programming knowledge. I suspect it is the middle in speed/ Does the speed matter though?
In this application , probably not. The bottleneck in performance is going to be in the I/O not the calculations. The performance of this function is lost in the noise.
What probably matters more, if one is looking to define “best”, is which algorithm is easier to understand..
I learned this lesson one day back when I was writing code for a living. We were doing a formal code review of my code and I had written what I thought was a very clever piece of code that was pretty efficient. The review made me rewrite it using code that was no where near as clever or interesting. It was, however, a lot easier for someone new to the code to understand. And that was more important.
Now there are applications where performance is critical. I remember working with a company building a system to collect weather data. They collected a huge amount of data is a very short period of time. They were actually comparing the instruction execution times of various machine language instructions to pick the computer they were going to buy. That’s pretty exceptional though.
To complicate matters even more, today’s optimizing compilers are very smart. It is rare that a person coded Assembly language program can outperform code generated by an optimizing compiler. I was involved in actual benchmarks of this in the 1980s and things are improved since then. Take these two pieces of code:
if (foo % 2 == 1)
label1.Text = "Odd";
if ((foo & 1)==1)
label2.Text = "Odd";
Which one is faster? You may think the second one is faster. You might be right. On the other hand, a really smart compiler by generate the same low-level code from both of them. Unless you were on the compiler writing team you probably don’t know. Even if you have the source code for the compiler do you really want to spend the time to see how it is optimized? You couple probably also look at the generated code but is that worth it either? Not generally.
The first example is clearer. A number of my friends who write code for a living tell me that is what they would use. Because it is clearer and understandable by more people it is not worth worrying about an optimization that may already be taken care of for them by the compiler.
Once upon a time it mattered a great deal if one iterated though a two dimensional array by column first or by row first. One had to know which was faster and do it right. Today, compilers take most of the worry about this away from us. We can do it in the way that seems more logical for us and for the application.
One of my friends who has worked on compiler development teams tells me that conversations about this sort of optimization are frequent there. People working on compilers have the time and the experience to make compilers smart. I’m pretty sure more of them (the people and the compilers) are smarter about code optimization than I am.
That doesn’t mean we can ignore performance. I’ve seen some beginner code that is horrible in performance. But still there are trade offs. I once wrote a very slow program that I ran once a month. I thought about a way to optimize it that would cut a minute or two off of the run time. It would have taken me an hour to code and that was a lot more time than it would have saved me. Turns out a faster computer a few months later ran the inefficient code a lot faster anyway.
Honestly, though discussion optimization and performance can be fun for a certain class of geek. Geeks like me.