Odnośniki
|
[ Pobierz caÅ‚ość w formacie PDF ] static. Nonetheless, dynamic memory allocation is sometimes unavoidable. In such cases, auto_ptr(discussed in Chapters 6 and 11, "Memory Management") simplifies the usage of dynamic memory. Effective and bug-free usage of the diversity of C++ memory handling constructs and concepts requires a high level of expertise and experience. It isn't an exaggeration to say that most of the bugs in C/C++ programs are related to memory management. However, this diversity also renders C++ a multipurpose, no compromise programming language. Contents © Copyright 1999, Macmillan Computer Publishing. All rights reserved. file:///D|/Cool Stuff/old/ftp/1/1/ch11/ch11.htm (23 von 23) [12.05.2000 14:46:35] ANSI/ISO C++ Professional Programmer's Handbook - Chapter 12 - Optimizing Your Code ANSI/ISO C++ Professional Programmer's Handbook Contents 12 Optimizing Your Code by Danny Kalev Introduction Scope of This Chapter Before Optimizing Your Software Declaration Placement Prefer Initialization to Assignment Relocating Declarations Member-Initialization Lists Prefix Versus Postfix Operators Inline Functions Function Call Overhead Benefits of Inline Functions What Happens When a Function that Is Declared inline Cannot Be Inlined? Additional Issues of Concern The Do's and Don'ts of inline Optimizing Memory Usage Bit Fields Unions Speed Optimizations Using a Class To Pack a Long Argument List Register Variables Declaring Constant Objects as const Runtime Overhead of Virtual Functions file:///D|/Cool Stuff/old/ftp/1/1/ch12/ch12.htm (1 von 22) [12.05.2000 14:46:36] ANSI/ISO C++ Professional Programmer's Handbook - Chapter 12 - Optimizing Your Code Function Objects Versus Function Pointers A Last Resort Disabling RTTI and Exception Handling Support Inline Assembly Interacting with the Operating System Directly Conclusions Introduction One often-heard claim during the past 30 years is that performance doesn't matter because the computational power of hardware is constantly dropping. Therefore, buying a stronger machine or extending the RAM of an existing one can make up for the sluggish performance of software written in a high-level programming language. In other words, a hardware upgrade is more cost-effective than the laborious task of hand-tuning code. That might be correct for client applications that execute on a standard personal computer. A modestly priced personal computer these days offers higher computational power than a mainframe did two decades ago, and the computational power still grows exponentially every 18 months or so. However, in many other application domains, a hardware upgrade is less favorable because it is too expensive or because it simply is not an option. In proprietary embedded systems with 128K of RAM or less, extending the RAM requires redesigning the entire system from scratch, as well as investing several years in the development and testing of the new chips. In this case, code optimization is the only viable choice for satisfactory performance. But optimization is not confined to esoteric application domains such as embedded systems or hard core real-time applications. Even in mainstream application domains such as financial and billing systems, code optimization is sometimes necessary. For a bank that owns a $1,500,000 mainframe computer, buying a faster machine is less preferable than rewriting a few thousand lines of critical code. Code optimization is also the primary tool for achieving satisfactory performance from server applications that support numerous users, such as Relational Database Management Systems and Web servers. Another common belief is that code optimization implies less readable and harder to maintain software. This is not necessarily true. Sometimes, simple code modifications such as relocating the declarations in a source file or choosing a different container type can make all the difference in the world. Yet none of these changes entails unreadable code, nor do they incur any additional maintenance overhead. In fact, some of the optimization techniques can even improve the software's extensibility and readability. More aggressive optimizations can range from using a simplified class hierarchy, through the combination of inline assembly code. The result in this case is less readable, harder to maintain, and less portable code. Optimization can be viewed as a continuum; the extent to which it is applied depends on a variety of considerations. Scope of This Chapter Optimization is a vast subject that can easily fill a few thick volumes. This chapter discusses various optimization techniques, most of which can be easily applied in C++ code without requiring a deep understanding of the underlying hardware architecture of a particular platform. The intent is to give you a rough estimate of the performance cost of choosing one programming strategy over another (you can experiment with the programs that are discussed in the following sections on your computer). The purpose is to provide you with practical guidelines and notions, rather than delve into theoretical aspects of performance analysis, efficiency of algorithms, or the Big Oh notation. file:///D|/Cool Stuff/old/ftp/1/1/ch12/ch12.htm (2 von 22) [12.05.2000 14:46:36] ANSI/ISO C++ Professional Programmer's Handbook - Chapter 12 - Optimizing Your Code Before Optimizing Your Software Detecting the bottlenecks of a program is the first step in optimizing it. It is important, however, to profile the release version rather than the debug version of the program because the debug version of the executable contains additional code. A debug-enabled executable can be about 40% larger than the equivalent release executable. The extra code is required for symbol lookup and other debug "scaffolding". Most implementations provide distinct debug and release versions of operator new and other library functions. Usually, the debug version of new initializes the allocated memory with a unique value and adds a header at block start; the release version of new doesn't perform either of these tasks. Furthermore, a release version of an executable might have been optimized already in several ways, including the elimination of unnecessary temporary objects, loop unrolling (see the sidebar "A Few Compiler Tricks"), moving objects to the registers, and inlining. For these reasons, you cannot assuredly deduce from a debug version where the performance bottlenecks are actually located. A Few Compiler Tricks A compiler can automatically optimize the code in several ways. The named return value and loop unrolling are two instances of such automatic optimizations. Consider the following code: int *buff = new int[3]; for (int i =0; i buff[i] = 0; This loop is inefficient: On every iteration, it assigns a value to the next array element. However, precious CPU time is also wasted on testing and incrementing the counter's value and performing a jump statement. To avoid this overhead, the compiler can unroll the loop into a sequence of three assignment statements, as follows: buff[0] = 0; buff[1] = 0; buff[2] = 0; The named return value is a C++-specific optimization that eliminates the construction and destruction of a temporary object. When a temporary object is copied to another object using a copy constructor, and when both these objects are cv-unqualified, the Standard allows the implementation to treat the two objects as one, and not perform a copy at all. For example class A { public: A(); ~A(); A(const A&); A operator=(const A&); }; A f() { A a; return a; } file:///D|/Cool Stuff/old/ftp/1/1/ch12/ch12.htm (3 von 22) [12.05.2000 14:46:36] ANSI/ISO C++ Professional Programmer's Handbook - Chapter 12 - Optimizing Your Code A a2 = f(); The object a does not need to be copied when f() returns. Instead, the return value of f() can be constructed directly into the object a2, thereby avoiding both the construction and destruction of a temporary object on the stack. Remember also that debugging and optimization are two distinct operations. The debug version needs to be used to [ Pobierz caÅ‚ość w formacie PDF ] |
|||
Sitedesign by AltusUmbrae. |