One of my favorite science-fiction authors, Robert Heinlein, wrote a book, The Moon is a Harsh Mistress, that concerns an artificial intelligence assisting in a revolution. In the book, characters use the acronym TANSTAAFL for “There ain’t no such thing as a free lunch”. The point being made was that you always pay for what you get, regardless of how it is buried in the presentation.
I grew up with constant reminders to beware double-edged swords: Tools that help us often turn and bite us if we are not careful how we use them.
Before I get back on my messaging hobby-horse, I’d like to consider some thoughts about our tools. I’ve already mentioned that I’m not too fond of interpreters or the thinking that “better hardware will make code cleanliness or efficiency unimportant” – I’d like to be the one to decide where I spend the power newer machines bring: new applications, better dynamic interactions, or the possibilities I’ve not yet thought of, and I do not want to be protected from myself.
One of my pet peeves is how poorly people understand floating point. Machines have become fast enough that there is no need to avoid its use, and we give lip service to dealing with rounding errors and the dislike of 2.00000000016 displays, but how many of us take the time to really understand it? In the dim dark prehistory before graphics, I tried my hand at compiler writing, which was not hard, but writing the run-time libraries was. I had to write an efficient software floating-point library, and later, when the 8087 introduced hardware floating-point to my world, make the compiler seamlessly use either. I’d recommend that anyone who writes code using floating-point read What Every Computer Scientist Should Know About Floating-Point Arithmetic.
Another pet peeve is making measurements with tools we do not take the time to understand. A common profiling technique is to take a statistical sample – what part of my code is being executed every so many msec? This is not a surgical tool – it tells you in which direction you should be looking. Times obtained this way do not include operating system functions, so a graphical function implemented outside WIN32 may take 4x as long as one using WIN32, but when you actually check, including time inside the WIN32 call, it might take half the total time. Moral: Be sure of what you are actually measuring.
Using a high-resolution timer is better, but you’d better average a few thousand tests, because Windows is a preemptive system. Michael Abrash’s book, Graphics Programming Black Book gives a lot of practical examples of measurement-driven design, although the hardware he discusses is now out of date. You also might want to download his Ramblings in Realtime. He has consistently shared his insights on thinking clearly about design.
The other tool that needs understanding is just what our compilers do with our code, and that means understanding assembler. I wrote our company’s FastCAD product entirely in x86 assembler. I actually started with the old Selector:offset horror, which I recommend everyone ignore as an historical bubonic plague. Once the 80386 and WIN32 supported the “flat memory model”, assembler became an order of magnitude (or more) easier.
I don’t recommend that you write programs in assembler. Modern compilers are efficient enough to please even me, and I no longer create in assembler. But the insight it gives me helps almost every day. It lets me judge the cost of various techniques used in C++. I learned that switch statements are no longer awful, since they are now implemented in optimized release code as a very efficient binary search. In fact, the more different cases, the more efficient such a test is. I learned that multiple inheritance is a real horror and can kill efficiency, and also lead to issues of functional duplication that can hide bugs.
I’d like to recommend the book, Write Great Code, Volume 2, by Randall Hyde. It gives a gentle introduction and walks you through both PPC and x86 compiler code generation. It may well surprise you and help you get better performance from your code, not because you will make minor changes for efficiency’s sake, but because being able to “think small” while “designing big” will improve the design approach you take.
Another book I like, out of the thousands on C++ programming, is C++ for Game Programmers. This is a very pragmatic book, and it is not about learning C++, it’s about using it. There is a 2nd edition by a different author, Michael Dickheiser, and they are different enough that I like having both of them. I have never programmed a game, but I read most game programming books, and subscribe to gamedeveloper magazine. These are the people who are really pushing the envelope, and there is a lot we can learn from them that will help us write any kind of interactive program.
Still another book I’d recommend is Raymond Chen’s The Old New Thing. I’ve just finished this, and found it very entertaining in the sense of “So thats why it had to suck!”. But on a much more useful level, understanding the reasons for so many of the WIN32 annoyances helped me understand the problems Window’s authors, and I, face in a deeper way, and occasionally, he gives some good code tips, such as the quick and dirty way to use Uniscribe to get rid of the “not in this font, you don’t” ugly boxes. I always thought there was no quick and simple way to use Uniscribe. This won’t take a lot of your time, and if even one of his points helps, it will be worth the money.
This entry (Permalink) was posted on Thursday, October 1st, 2009 at 6:35 pm and is filed under Uncategorized. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.