Search Tips Advanced Search |
| Delphi Graphics and Game Programming Exposed with DirectX 7.0 by John Ayres Wordware Publishing, Inc. ISBN: 1556226373 Pub Date: 12/01/99
Search this book:
Previous | Table of Contents | Next
### Additional Optimization Considerations Developers are always discovering new tricks and techniques to squeeze a little more performance out of an application. The topics we’ve covered have only scratched the surface of the myriad of arcane programming constructs that programmers use to improve performance. Beyond the specific optimization techniques we’ve discussed in this chapter, developers should be aware of general coding practices that should help improve overall performance. Memory allocation is one of those key areas that can dramatically affect the performance of an application. The task of dynamically allocating memory is an expensive one in terms of time. If possible, you should always dynamically allocate all memory up front, when the application starts. Of course, this is only possible if the total amount of required memory can be determined when it is allocated. If it is impossible to determine the total amount of required memory, try allocating the memory in larger blocks, using up the allocated memory until more is needed. For example, if you’re using dynamic arrays, instead of allocating one entry at a time, try allocating 10 entries at a time and using those 10 until more are required. This results in fewer dynamic memory allocations, which in turn results in better performance. As an alternative to dynamic memory allocation, you may want to try using only global variables. Global variables cause the system to allocate their memory when the application starts; by using only these global variables, you never have to dynamically allocate memory, and thus never incur the cost of such a task. Of course, this may only be applicable if the number of variables required is not too great. Otherwise, the hassle of managing such constructions in terms of coding and code maintenance may outweigh the speed benefits. Another advantage to using global variables is that they can be used within local functions without creating a stack. In this manner, you could potentially pass hundreds of parameters to a procedure or function without creating and initializing a data structure as discussed above. You have all of the disadvantages associated with using global variables in such a manner, but you may be able to utilize this method in a limited fashion where you need both speed and a large parameter list. Constant arrays are another area that one should look at. Constant arrays are easy to maintain, but their use incurs an array dereference. If possible, simply use several constants instead. This may be harder to maintain in the long run, but you avoid the array dereference, and ultimately it will improve performance where the constants are used. However, where optimization is paramount and speed is critical, one may have to drop down to assembly language. It’s hard to beat the speed of hand-optimized assembly. Unfortunately, assembly language, even verbosely documented, is both hard to maintain and hard to modify. It also takes a developer experienced in assembly language to do a decent job. Assembly language can be written right in the Delphi IDE; you simply have to enclose it within an asm..end block. An assembly language tutorial is beyond the scope of this book. However, several general Delphi books contain discussions of using assembly language within Delphi, and many good 32-bit assembly language references are available. Fortunately, with the speed of today’s machines and Delphi’s optimizing compiler, the use of hand-optimized assembly is not quite as necessary as it was just a few years ago. ### Summary In this chapter, we discussed several techniques for improving the performance of games and applications. We looked at the optimizations that Delphi performs, as well as some Delphi-specific optimization techniques. We also examined some general optimization techniques that are language independent and discussed further optimization considerations. When optimizing your Delphi applications and games, it is important to keep these points in mind: • The most important step in optimization is knowing where to optimize. After you’ve determined where the bottlenecks are in application execution, the next step is to evaluate the problem and determine how to optimize the code. Never guess at where your bottlenecks might occur; either use a profiler or some technique for timing code execution. • Reevaluating an algorithm can have a greater impact on performance than any collection of singular optimization tricks or techniques. • The task of optimization has a diminishing margin of returns. Spending 10 hours to improve performance by 10% may be worthwhile; spending another 10 hours to improve performance by only 1% is probably a waste of time. • Optimization should be the last task in application development. Trying to optimize code halfway through the development cycle can be a waste of time, especially if the optimized code gets cut out in favor of another method. • Never spend time optimizing code that is only called once or twice throughout the entire execution of an application. The most common place to begin optimization is within loops, specifically inner loops that may be performed thousands of times. • Delphi itself offers a number of very useful optimization options. The compiler itself performs quite a few automatic optimizations, such as register optimizations, call stack elimination, common subexpression removal, the use of loop induction variables, and dead code elimination. Other optional compiler optimizations include aligned record fields, elimination of stack frames, range checking, and overflow checking. • Exceptions should only be used when an error occurs that must be responded to. Never use exceptions to account for errors (such as dividing by zero), as they are incredibly slow. • Virtual methods are optimized for speed, and dynamic methods are optimized for size. However, static methods are the fastest as they do not incur a dereference. • Never use a variant when a standard data type will do. Bear in mind that some standard data types are faster than others for certain operations. • Avoid using strings as parameters or as return values from functions, as this implicitly creates extra code that slows down the application. • Loops should be unrolled so as to reduce the number of jumps the application performs. • Lookup tables should be used for mathematical functions and equations when a finite range of input values is known. • When multiplying or dividing by a power of 2, using binary bit shifting, as this takes advantage of hardware available in every PC.
Previous | Table of Contents | Next

Products | Contact Us | About Us | Privacy | Ad Info | Home Use of this site is subject to certain Terms & Conditions, Copyright © 1996-2000 EarthWeb Inc. All rights reserved. Reproduction whole or in part in any form or medium without express written permission of EarthWeb is prohibited. Read EarthWeb's privacy statement.