Latest ArticlesEngine Architecture #1
Static Shadows #1
Paint on Mesh
A Tale of the Internet
Optimizing Code Mar 01, 2006
Many years ago I used to optimize at a low-level. I'd peruse my software routines for rendering texture mapped polygons, and rewrite them in assembly to squeeze the most speed out of them possible. I almost never do anything like this anymore. The main reason might just be a change of interests, although I also feel the move away from this type of optimization is natural. Compilers are better at optimizing now, graphics cards take care of filling video memory with pixels, and my programs are complex enough that rarely is there a single area of code where this seems worth it. I do still sometimes work on a single function to make it faster, but this is of less importance than high-level optimizations.
High-Level OptimizationFor complex programs, like 3D Kingdoms Creator, I think most of the optimization I do can be summed up by saying this: Avoid needless work. The first way to avoid needless work is not to recalculate what you don't need to. When I first started doing serious optimizing on 3DKC a couple years ago, I was surprised to find that quite a few calculations were being redone needlessly. By changing the flow of the program and changing data placement they'd only need to be done once. (Maybe if I had more previous experience writing a program with many different object types, animation types, rendering options, and multiple viewing windows, I would have done better initially.) There is sometimes tradeoff here with memory usage, as you'll need save in memory results that could be useful again.
By avoiding needless work I also mean don't render objects that are not visible( by methods such as frustum-culling, and using portals for occlusion and visibility calculations.) With per-pixel lighting avoid calculations for lights on objects they don't hit, either because they're beyond light's influence radius, or because they're occluded, or in the case of projector lights, not in the projector's frustum. There's also not rendering details when they're too far to see, by using Level of Detail on meshes that are far away from the camera, or fading out then not rendering distant particles.
Profiling CodeProfiling programs are very helpful when you need to find where the CPU cycles are going. The CPU in my main development computer is currently an AMD 3500+. To profile code on AMD CPUs, you can download the AMD's CodeAnalyst Performance Analyzer. Compile your code in release mode as usual, but generate debug info as a program database. In Microsoft Visual C++ this is found in the configuration properties->linker->debugging-> generate debug info and c++ ->general->debug info format. Now you can profile your code to see which functions take up the most CPU time, and optimize those functions or avoid calling them so often.