Improving C Program Performance (Dr Dobb's Journal October 1999/10.) Author: Stanley Lippman Translator: Chen Wei Hou Jie's Note: This article Department of Beijing "programmer" magazine of 2001/12. Mr. Chen Mr. Chen Mr. Chen, a person in charge of "Programmer" magazine, is reproduced here, thank you for Taiwan readers.
Mr. Chen, Mr. Chen and Mr. Jiang Tao did not reprint this article.
-------------------------------------------------- ------------------------------
Translation: The following is a variety of terms used in this article:
Instance: entity.
Terms such as Class, Object, Data Member, Member Function, Constructor, Destructor, Template are reserved.
-------------------------------------------------- ------------------------------
For C programmers, do not define Copy Constructors, Copy-Assignment Operators, Destructors, and its importance is just just as it is necessary to cognition these special Member functions. For example, consider the test results of a table:
Optimized Basic Mode 28.59 15.22 Modify # 1 22.25 (22%) 12.27 (19%) Modify # 2 15.88 (44%) 9.50 (37%) Integration (# 1 and # 2) 12.97 (54%) 7.51 (51%)
Table 1: Test results for execution time
The "Basic Model" column is presented, is an execution time with a program with the entire group specialization MEMBER FUNCTIONS (Copy Constructor, Copy-Assignment Operator, Destructor). In this basic model, there is no Class Member Functions or any of the Friend Functions it supports is announced as inline. Yes, do not use inline, three special Member functions, and quite extent in line with universal popular C programming rules (such as Taligent's Guide to Designing Program, Addison-Wesley, 1994, ISBN 0-201-40888-0) ).
In order to continue discussions, we assume that this program is too bad, and your job is to make it fast. What should you do?
There are three common acceleration strategies:
1. Replace the current algorithm currently used in more efficient algorithms (but such ranking algorithms are often more complex, for example with fast sorting method Quicksort substitution bubble sorting method bubble sort).
2. Replace the data structure used in more efficient data (but such data structure is often more complex, for example, with red-black tree Red-Black Tree replaces binary tree binary Tree).
3. Replace the program code currently used in more efficient programming (in this case, the efficiency increases is often accompanied by the reduction in process and program readability).
In many cases, any one of the three strategies in the above three strategies is actually unnecessary. Typically, review and pick out an inappropriate C programming technique, not only simple and good. The so-called inappropriate programming habits, one of which is unnecessary to define Copy Constructors, Copy-Assignment Operator and Destructor. List one performance is a basic model of Vector Class and its application (translation: This vector does not refer to the container provided by the C standard program, but the three-degree space vector in the budology), the first modification is just Simply change each Friend Function and Member Function to Inline. The second modification is removed in addition to the Copy Constructor, Copy-Assignment Operator and Destructor definitions. The third revision is the combination of the first modification and the second modification. These programs listed in this article pass through the SGI 7.2 compiler, and the time measurement is completed by the TIMEX instruction. Listing a class Vector {friend Vector operator (const Vector &, const Vector &); friend Vector operator- (const Vector &, const Vector &); public: Vector (double x = 0.0, double y = 0.0, double z = 0.0); Vector ( Const vector &; vector & operator = (const vector); ~ vector (); bool operator == (const vector &); Vector Operator / (double);
Double MAG (); Double Dot (const vector &); void normalize ();
Double x () const; double y () const;
Void x (double newx); void y (Double newy); Void z (Double newz);
Private: double _x, _y, _z;}; vector :: vector (double x, double y, double z) {_x = x; _y = y; _z = z;} vector :: vector (const vector) {_x = rhs._x; _y = rhs._y; _z = rhs._z;} Vector :: ~ vector () {_x = 0.0; _y = 0.0; _z = 0.0;} vector & vector :: operator = (const vector & rhs) {_X = rhs._x; _y = rhs._y; _z = rhs._z; return * this;} VectorOperator (Const Vector & lh, const vector & rhs) {Vector Result
Result._x = LHS._X RHS._X; Result._Y = LHS._Y RHS._Y; Result._Z = LHS._Z RHS._Z; RETURN Result;} VECTOROPERATOR- (Const Vector & LHS, Const Vector & RHS {Vector Result;
Result._x = lhs._x - rhs._x; result._y = lhs._y - rhs._y; result._z = lhs._z - rhs._z;
Return Result;} # include
Result._x = _y * rhs._z - rhs._y * _z; result._y = _z * rhs._x - rhs._z * _x; result._z = _x * rhs._y - rhs._z * _y;
Return result;} void vector :: normalize () {double d = MAG (); _x / = D; _y / = D; _Z / = D;} Double Vector :: Dot (const vector & rhs) {return _x * rhs ._x _y * rhs._y _z * rhs._z;} BOOL Vector :: Operator == (const vector & rhs) {return _x == rhs._x&& _y == rhs._y&& _z == rhs._z } Vector :: Operator / (double val) {vector result
IF (VAL! = 0) {result._x = _x / val; result._y = _y / val; result._z = _z / val;} return result;} Double Vector :: x () const {return _x;} Double Vector :: Y;} Double Vector :: z () const {return_z;}
Void vector :: x (double newx) {_x = newx;} void vector :: y (double newy) {_y = newy;} void vector :: z (double newz) {_z = newz;
#include
vv.push_back (a.cross (c)); vv.push_back (A C); vv.push_back (a - c); vv.push_back (a / c.mag ()); vv.push_back (a.cross (c)); if (c == a) vv.push_back (b); else vv.push_back (a);
C. Normalize (); vv.push_back (c);}} First modification: Plus Inline first modification action is to "Inline" in "inline". This change is really easy: Just add keyword inline to each of your goals you want to modify. You suddenly increase the efficiency of about 20%. In general, an application is not "Inlineing" to the appropriate "Inline", and is estimated to obtain 20% to 25% efficiency.
If INLINING brings the promotion of program efficiency, you don't need to have a significant effort, why do many programming standard brochures do not agree with "Inlineing"? Yes, its main disadvantage is that you must recompile each file of "Inline Version". For a Class Library applied to a large-scale task, recompile cost is quite expensive.
When you add or remove its Data MEMBER in C , or when you modify the model of a existing Data Member, the same problem will also appear. In order to completely solve the recompilation problem, you need to transfer to another object model (Object Model), such as the object mode supported by COM (you can test Essential CoM, by Don Box, Addison-Wesley Longman, 1998, ISBN 0 -201-63446-5; and Inside THE C Object Model, by Stanley Lippman, Addison-Wesley, 1996, ISBN 0-201-83454-5).
It is for sale in the project programming standard manual, which is actually a misleading. But from another perspective, it is not every C function that should be inline. Another potential disadvantage of Inline is the expansion problem of the program. In general, only a small letter (for example, the MEMBER FUNCTIONS for a vector is suitable for INLINE. How to take care of the actual use, waiting for your wise judgment.
Second modification: Show unless necessary MEMBER FUNCTIONS second modification is to remove the unnecessary CONSTRUctor, Copy-Assignment Operator, and Destructor, which removes the VECTOR CLASS. (For this modification, I let all Member functions become noninninline. In the third modification, I will integrate both.). This change is even more directly easy than the inline; you only need to delete the declaration and definition of three functions. The result is a few of the efficiency of nearly 40%.
Such a result tends to bring the programmer to a great surprise, but if you understand the behavior at the bottom of the compiler, you will not be surprised.
When is there any obvious Copy Operators? Preset, a class object is initialized or assigned by "MEMBERWISE COPY". On the concept, take the Vector Class as an example, first is the X coordinate, then the Y coordinate, then the Z-coordinate is copied by the Turban. Just like your written code, please see the list one. However, in fact, the compiler is not copied to Objects in the above manner:
It does not produce a significant Copy Constructionor and Copy-Assignment Operator. It does not turn to copy every Data Member representing the value of the icon, but directly "Bitwise Copy" directly on the entire Object, just like C's behavior. The compiler does not produce a preset MemberWise function. The actual code (list) and the compiler have a dark behavior, and the two are very large, and it is obvious to the efficiency performance. Is this true for all? No, in general, the compiler will synthesize a COPY Constructor and a Copy-Assignment Operator in four cases:
When the Class contains a MEMBER CLASS Object, the latter has a corresponding Copy Constructor and / or Copy-Assignment Operator. When Class is derived from one or more base classes, the latter has a corresponding COPY Constructor and / or Copy-Assignment Operator. When Class declares or inherits a virtual function. Direct or indirectly derive from a Virtual Base Class directly or indirect. C Standard will call such classes as NontriVial. In other words, the aforementioned Vector Class is TriVial, that is, it does not meet the above four cases. (More detailed discussion, please see my book Inside the C Object Model.)
So, do you never define a Copy Constructor and Copy-Assignment Operator? of course not. It is necessary to provide an explicit definition for them in some cases. The most common need is to include one or more Pointer MEMBERS in your class, while the latter is not initialized during the Class Object life, that is, the value of a piece of HEAP memory, then the memory is then Destructor is deleted. One of the basic views of C programming is to know this situation. If you need more comfortable and instance discussions, please see C Primer, the third edition, by Stanley Lippman and Josée Lajoie, Addison-Wesley Longman, 1998, ISBN 0-201-82470-1.) (Translation: You can also read Effective C 2 / E, Terms 11: "If the Classes internal dynamically configures memory, please CLASS declared a Copy Constructor and a Copy-Assignment Operator." All Data Members exists in by value mode " For example, Vector Class, the compiler preset initialization action and copy action will be more efficient than our own writes. This is a very small amount of work for programs and programs. For pristines, your task is to identify what it requires yourself in an explicit COPY CONSTRUctor and Copy-Assignment Operator.
When is an Explicit DESTRUctor? The same principle is the same, and "all Data Members exists in the BY Value mode", Destructor is not necessary. Yes, not every Class requires Destructor, even if you have provided one or more constructors for this Class. The DESTRUCTORS task is mainly withdrawn from the resource obtained by the Constructor, or the resources you have requested during the Life of the Class Object. For example, a multi-worker muto lock is released, or the "Operator New;" Configured Memory ", please test C Primer.
Why is it not a recommended programming technique? If you do not provide explicit Copy Constructor and Copy-Assignment Operator and Destructor, you can improve your program efficiency, but don't need to do more, why do many programming standard manuals suggest that we try to provide an explicit version? This topic, I believe that involving the possibility of a countertop, that is, as a C pristine, have you got enough trust to play your judgment? (Said the range, the INLINING topic is also the same.) To know, in case they (those special Member functions) must exist, but you don't provide its physical body, which will result in serious program errors.
How to choose? One of the ways is to allow you to choose freely, premise is "All necessary information before making correct choices" must be complete. The second of the way is very simple ink, usually, usually these (programming standard manual) rules apply in the case of 80% - 90%. The choice between the two solutions is related to how you manage a software project. In Vector Class, provide non-necessary Copy Constructors, Copy-Assignment Operator, Destructor's explicit entity, is not incorrect, but the efficiency is not. Cognition this fact helps you adjust your actual code without having to renrove it.
Acknowledgments Josée Lajoie reviewed the first draft of this article and provided many profound views and suggestions.