s programming languages have evolved over the years, the challenges in optimizing and fine-tuning applications have changed. I began programming 20 years ago and quickly adopted assembler language for its fast performance and small footprint. However, coding in assembler meant that I had to do everything myself. If I wanted to draw to the screen, I wrote a line-drawing routine. If I wanted to use floating-point arithmetic, I wrote the floating-point routines. Magazine articles and advice from other developers helped, but the onus was on me to write every byte of the code.
Although this level of responsibility was tricky, having the code under my complete control had its advantages. If it was slow, I could pinpoint the performance glitch and fix it myself. Nowadays, a developer wouldn't dream of designing his own fonts or writing his own printer drivers. All this commonly used functionality has been wrapped up in black boxes and given away or sold in components. The challenge no longer lies in low-level programming; it's in integrating pre-packaged bits of code largely written by other peopleand making sure they perform at their optimum levels. The performance of your application will depend largely on third-party components whose implementation is hidden, and over which you have no control.
Take, for example, the Microsoft .NET class libraries, an object-oriented layer that Redmond has spent a lot of time developing. This layer sits on top of the operating system to provide .NET functionality, which reminds me of the expression "putting lipstick on a pig." Microsoft has applied the lipstick in thick layers, but the OS underneath is still piggish. If you forget that parts of it were designed over a decade ago and are in no way object-oriented, you can encounter problems when you try to optimize your .NET applications.
Granted, all code is ultimately just a bunch of non-object-oriented machine code, but Microsoft could have implemented the .NET performance counters (features that gauge how CPU levels, memory usage, disk I/O, and other functions are performing) at the OS level in an object-oriented fashion. In fact, developers might assume Redmond did just that if all they can see is the .NET wrapper, but layers such as .NET provide a veneer of object-oriented classes over an underlying system that is not. This means a big disparity could exist between how a developer assumes a call will work and how it actually does.
A good way of avoid these pitfalls is to keep an eye on what your code is actually doing and how long it is taking to do it. A number of tools can help you do this. The ones I used to write this article include ANTS Profiler from Red Gate Software, the Anakrino .NET decompiler, and Microsoft's .NET Allocation Profiler.
|Editor's Note: Guest commentator Neil Davidson is the technical director at Red Gate Software, a vendor of code profiling software tools.