When we develop software development, if the code is relatively small, we can easily master, understand the implementation of the program, but when the code exceeds thousands of lines, especially when tens of thousands of lines, we will hardly master the program. Process, in this case, code tracking is a very important thing. Code tracking technology, for most programmers, is to define a relatively simple Trace class, output the information information, generally writing a message in the entrance of the program, writing a message in the outlet of the program, although this is Time performance is at the expense, but it helps we find the problem without using the debugger. The most extreme case is through the #ifdef switch, completely eliminate performance overhead, but it is necessary to recompile if it is turned on / off, and it is obvious that the final user of the program cannot do so. So only the tracking control is performed by dynamic communication with program communication. First, in order to obtain a program execution time, let's define a simple test performance class. The name is called Timer, implemented as follows: Class Timer {public: timer (): start ()) {} ~ time () {COUT << "The time is:" << Clock () - start << end1;} private: clock_t start;}; Next, we will define a simple tracking class Trace, which is initially implemented as follows: Class Trace { Public: trace (const string & name); ~ trace (); static bool trace_active; private: string thename;
Bool TRACE :: trace_active = false;
Inline TRACE: TRACE (const string & name): Thename (name) {if (trace_active) cout << "Enter the function:" << name << endl;}
Inline trace :: trace (const char * name): Thename (name) {if (trace_active) cout << "Enter the function: << * name <<" ms "<< Endl;}
Inline trace :: ~ trace () {if (trace_active) cout << "exit the function:" << "" Endl;} Next we test, first define a simple function: int F (int x) { RETURN X 1;} Time Expenses for Testing: Int Main () {Timer * Time = New Timer; Trace :: Trace_Active = false; for (int i = 0; i <1000000; i) f i); delete Time; RETURN 0;} The output time is 30ms. Next, we open the tracking function: int F (int x) {trace trace ("f"); returnix x 1;} TRACE: TRACE_ACTIVE = FALSE; simultaneously turn the I / O close, tested again, the results are as follows: 1892ms Here we have seen time increased by 62 times, the main performance source is (1) "f" in the constructor to convert to String type, (2) The construction and destructuring of the THENME. It seems that it affects 1/3 efficiency, is this? Below, we cancel "f" to convert to a String type overhead: add a constructor: TRACE (const char * name): tell (name) {if (trace_active) cout << "Enter the function: << Name < <"ms" << Endl;} Test again, the results are as follows (off I / O): The improvement of 1690ms performance does not seem to be as high as we expected, why? Is it difficult to have an IF (trace_active) affects test results? We turn this judgment statement to test again, and the results are as follows: 1646ms. Still a difference, is not 1/3 of data, is it the impact of parameter transmission? This time we took thename and see how much time it takes up in the class itself, and then tested again. The result is as follows: 153ms. Analyze the above data: The parameters of the class itself take up 153ms, and if the IF judgment statement takes up 44ms, then the construction and destructure of 1493ms, "F" is converted into string 202ms, so our main goal should be concentrated in thename. Above, we will use combination to replace aggregate to see performance changes: Class Trace {public: trace (const string & name); ~ trace (); static bool trace_active; private: string * thename;}; bool trace :: trace_active = False;
Inline trace :: trace (const string & name) {if (trace_active) {cout << "Enter the function:" << name << endl; thename = new string (name);}} inline trace :: trace (const char * name) {if (trace_active) {cout << "Enter the function:" << * name << "ms" << endl; thename = new string (name);}}
Inline trace :: ~ trace () {if (trace_active) {cout << "exit the function:" << * thename << Endl; delete thename;}} test result is 2682ms, compared with us using aggregation, time increase 58.70%, it seems that it is really cost to create objects on the pile. But in the book, this time, time is reduced by a quantitude, this is what I can't understand, if anyone has seen this book, please tell me, thank you!
Conclusion: From the above analysis, we can see that a small function is relatively large, affecting the performance of the program. Therefore, it is suitable for inline, it is not suitable for tracking, the Trace object should not be added to the frequently used small functions.
Note: The above data is under DEV-C 4.9.5.0 and Win2000, each set of data is tested 10 times, and the average is worth it. In addition, in the above data test, I have never opened I / O because I / O is too time consuming, don't believe, you open.