9ProgramEfficiency
9.1 performance classification of c ++ Language Features
There are many factors that affect the software performance, including the software architecture and operating platform (Operating System/Compiler/hardware platform. Many times
The performance of sequence has been determined when the framework design is complete. Therefore, when the performance of a program needs to be improved, the first thing to do is usability.
The detection tool can accurately measure the running time distribution, find out the key path and the real bottleneck, and then target the bottle.
Analyze and optimize the neck, rather than blindly blaming the language for poor performance. In fact, if the framework is not designed
Modification, that is, using the C language or the Assembly Language to rewrite, does not guarantee to improve the overall performance.
C ++'s performance design principle is zero overhead, which means you don't have to pay for what you don't choose
Pay for what you don't use), so you need to understand the performance overhead of various C ++ language features. Performance description of C ++ Language Features
Free/cheap/expensive classification is used.
Free;
Cheap: the performance overhead can be used in most cases. Pay attention to the key points of performance;
Expensive.
C ++ language features performance classification remarks
The struct of the Free Class and C is the same in the space used. The member letter in the class
The time overhead of the number is also equivalent to that of the CCodeIs consistent.
Multi-state free classes containing virtual functions need to add virtual table pointers (4 bytes) in space.
Overhead of indirect addressing is required for the execution of virtual functions. Although there is a small amount of overhead
Equivalent to C equivalent code.
The namespace free namespace will increase the length of the symbolic name string, but the c Equivalent code is also
You need to add a prefix string (such as the module name ).
Implicit inline free has no overhead for function calls, and execution without command redirection can enable the Compiler
For better optimization, but it will increase the program size.
Overhead of reload free equivalent class member functions
Overhead of constructing and destructor free equivalent class member functions
Reference free equivalent or better than pointer usage
Reference can avoid overhead of indirect addressing of pointers.
Template free ~ The template has the advantage of static polymorphism, and some logics are advanced to the compilation stage to improve
Expensive performance; but it will lead to code expansion and program size increase.
Rtti cheap ~ The execution time is time consuming. the overhead of dynamic_cast in gcc/VC is less than 10.
Expensive times function call, increasing program size.
Exception expensive exception capture is time-consuming, including stack expansion and other operations, exception handling in gcc/VC
The overhead is greater than 300 times the function call.
STL cheap ~ STL provides different linear (list), log level (MAP), and constant level (hash_map)
Expensive performance container, it is recommended to choose according to the actual needs of the application.
For more information, see extended reading materials:
1. Technical Report on C ++ performance ISO/iec pdtr 18015,2003-08-11
2. the inefficiency of C ++, fact or fiction? Anders Lundgren, IAR Systems
3. Programming Technology for improving C ++ performance, by Dov bulka and David Mayhew.
9.2 performance optimization guide for C ++
Principle 9.1 first measurement and optimization to avoid immature Optimization
Note: performance involves many factors. It is difficult to significantly improve the performance of language-level optimizations with unclear objectives. We recommend that you measure the performance first.
Performance bottleneck, and then optimize these performance bottlenecks. A common mistake for beginners is that they are excited when writing code.
Optimization sacrifices the comprehensibility of the Code.
Principle 9.2 select appropriateAlgorithmAnd Data Structure
Note: code optimization should begin with selecting an appropriate algorithm and data structure. Search for data with more than 1000 elements in sequence
The algorithm efficiency is much lower than the search algorithm with log performance. STD: vector <int> occupies about N * sizeof (INT), while
STD: List <int> occupies about N * sizeof (INT) space ). STD: Map provides a logarithm-level search algorithm, while hash_map
Higher, providing constant-level search algorithms, but hash_map needs to select an appropriate hash algorithm and bucket size.
We recommend that you replace the value assignment with initialization in the constructor 9.1.
Note: initialization through the member initialization list is always legal, and the efficiency is higher than assigning values in the constructor.
Example:
Class
{
String S1 _;
Public:
A () {S1 _ = "Hello, world ";}
};
In fact, the generated constructor code is similar to the following:
A (): S1 _ () {S1 = "Hello, world ";}
The default constructor of member S1 _ has been implicitly called. The initialization in the constructor is actually called operator =
The initialization list only needs to call the S1 _ constructor once, which is more efficient.
A (): S1 _ ("Hello, world "){}
9.2 beware of the overhead of empty constructors or destructor
Note: The overhead of an empty constructor is not necessarily 0. The empty constructor also includes the construction of base classes and member objects within the class. If
Constructor or destructor has considerable overhead. We recommend that you avoid using temporary objects and avoid non-
Construction and Analysis of temporary objects, such as lazy/eager/partial acquisition design mode.
Class y
{
C;
D;
};
Class Z: Public y
{
E;
F;
Public:
Z (){};
};
Z; // initialization of C, D, E, F
We recommend that you pass the reference (priority) or pointer instead of passing the value as much as possible for the object parameter 9.3.
Description: it is safe and simple to transmit values of the value type such as int and Char. However, it is applicable to custom objects such as class, struct, and union.
For example, transferring a reference is more efficient:
No need to copy. Objects such as class are generally larger than references, and may contain implicit data members and virtual function pointers.
So the cost of copying a value is much higher than that of a reference.
No need to construct or analyze the structure. If the value is passed in, it is used to call the copy constructor and analyze the structure when the function exits.
It is helpful for functions to support derived classes.
For details about the reason for preference, see Recommendation 3.2.
Example:
Void F (t x) // bad
Void F (t const * X) // good
Void F (t const & X) // good, prefer
We recommend that you reduce the number of temporary objects by 9.4.
Note: Temporary objects are generated in the following conditions: expressions, function return, default parameters, and suffixes ++. Temporary objects must be created.
Create and delete. For non-small objects, creation and deletion costs a lot in terms of processing time and memory. Use the following method:
To reduce the generation of temporary objects.
Use parameters of the reference or pointer type instead of directly passing values;
Replace ++ with ++ =
Use an anonymous temporary object;
Avoid implicit conversion;
Example:
Matrix;
A = B + C; // bad: (B + C) creates a temporary
Matrix A = B;
A + = C; // good: no temporary objects created
We recommend that you prioritize the use of pre-auto-increment/auto-increment in 9.5.
Note: The post ++/-- is to copy the object to the temporary object, and then return the temporary object. This process is performed in a non-simple number
Data type is time-consuming (simple data type compiler can be optimized)
Example:
For (list <X >:: iterator it = mylist. Begin ();
It! = Mylist. End ();
++ It) // good: rather than it ++
{
//...
}
We recommend that you use inline functions as much as possible in the 9.6 simple access method.
Note: frequent jump of small functions results in performance loss. inline functions can avoid performance loss.
Class X
{
PRIVATE:
Int value _;
Double * array _;
Size_t size _;
Public:
Inline int value () {return value _;}
Inline size_t size () {return size _;}
};
Recommendation 9.7 review the performance specifications of the standard library
Note: STD: string is a huge class. Improper use (such as a large number of + operations) can cause rapid performance degradation;
STD: List <t>: size () is linear in some implementation versions. Therefore, you can use if (mylist. Size () = 0)
If (mylist. Empty () replacement; standard input and output are performance bottlenecks. If the standard input and output libraries of C ++ and C are not mixed, you can test
Disable synchronization: STD: ios_base: sync_with_stdio (false ).
We recommend that you reload the dynamic memory manager with the object pool 9.8.
Note: system calls New and delete involve complex processing such as system calls. The time and space overhead are large, and doupa memory is used.
The application mechanism is similar. We recommend that you use a custom object pool mechanism to manage the application and release of a specific class.
Please release and release without the memory management mechanism of the operating system or doupa. The size of the Object pool needs to be determined in advance or similar
The STD: vector. Resize () method can dynamically increase.
We recommend that you pay attention to the initialization efficiency of large-sized arrays in 9.9.
Note: We often initialize arrays as follows:
Char szaccount [max_account_len] = {0}; // array size 16
Ensure that there is an Terminator for the string, so you should replace it with "szaccount [0] = 0;" for initialization. Of course, it is not critical.
The initialization code of the above line of code is more concise and acceptable.
Char chtempbuff [max_msg_len] = {0}; // The array size is 40 K.
For such a large piece of memory to 0, we should replace it with the memset and other database functions. When the compiler is not optimized
Usually, one byte is assigned 0 values one by one, while memset may be eight bytes at a time on a 64-bit platform. Therefore, when the number of arrays is greater than 10
Bytes, the performance gap between the two is 2 ~ 8 times, depending on the array size.
In particular, an array of large objects is generated or deleted. The constructor or destructor of each array member must be called once.
More time.
It is recommended that 9.10 avoid small memory allocation within the Function
In this example, a function allocates memory based on the message length and then performs related operations. before exiting the function, the memory is released as follows:
Char * PMSG = new char [msglen];
In fact, the lifecycle of PMSG is only within the function, and the memory it points to is actually a temporary variable. If we can predict its
The maximum length is much smaller than the thread stack space. For example, the maximum length is dozens of kb or only dozens of bytes.
Array, as follows:
Assert (msglen <= max_msg_len); // in some cases, if detection may be required, but assert detection may be inadequate.
Char chmsg [max_msg_len]; // there is no failure or release processing, and the efficiency is not an order of magnitude.