C ++ application performance optimization (three) - Performance Analysis (1) C ++ language features

C ++ application performance optimization (three) - C ++ language features performance analysis

A, C ++ language features Introduction to Performance Analysis

Usually most developers think, assembly language and C language more suitable for the preparation of very high performance requirements of the program, C ++ language is mainly used in the preparation of complexity is very high but not very high performance requirements of the program. Because most developers think, C ++ language design when considering that supports multiple programming models (such as object-oriented programming and generic programming) as well as exception handling, thereby introducing too many new language features. New language C ++ compiler characteristics have been inserted such that a lot of extra code when compiling the program, cause the final volume expansion generated binary code, and execution speed decreases.

But it was not usually a speed of roughly program have been identified in the framework design is complete, and not because the use of the C ++ language that led to the speed did not meet expectations. Therefore, when the need to improve the performance of a program, you first need to do it is to use performance testing tool for its running time distribution an accurate measurement, to identify the critical path and the real performance bottlenecks, and then analyzed for performance bottlenecks and optimization, rather than subjectively attributed the performance issues language program used. Engineering practice shows that, if the frame design will not be modified, even using C language or assembly language rewrite, also does not guarantee that improve overall performance.

Therefore, you experience performance problems, first check and reflect on the overall architecture of the program, and then use its actual operating performance testing tool to make accurate measurements, and then analyzed and optimized for performance bottlenecks.

If you have wanted to learn c ++ programmers, you can come to our C / C ++ learning buckle qun: 589348389,
free delivery C ++ Video Tutorial Oh!
Each 20:00 I will live in the group to explain the C / C ++ knowledge, welcome everyone to learn Oh.
 

But the C ++ language does have some operational characteristics more likely to become a performance bottleneck procedures than other factors, common factors are as follows:

(1) missing pages

Missing pages usually means that to access external storage, because the external memory access with respect to access memory or code execution, an order of magnitude difference. Therefore, whenever possible, should try to find ways to reduce the missing pages.

(2) from the stack dynamically and freeing memory

C language malloc / free C ++ language and new / delete operation is very time consuming, so to get priority from the thread stack memory as possible. Give priority to reduce the dynamic heap and stack memory applications, not only because the heap memory allocated on the stack than the much slower, but also to minimize the missing pages related. When the program is executed, the current stack frame memory page space located in physical memory affirmative, the program code wherein variable access does not cause a page fault; generating an object from the heap space if only pointer to the object on the stack, the object itself is stored in the heap space. Generally not possible to stack in physical memory, and since the characteristics of heap memory allocation, even if two adjacent objects generated, most likely far apart in the heap memory location. Therefore, when two objects are accessed, although two are pointers to objects are on the stack, but is likely to cause a page fault when the two objects referenced by two pointers.

(3) complex object creation and destruction

Create complex objects and destruction would be more time-consuming, so for deeper levels of recursive calls need to focus on objects inside recursively create. Second, the compiler-generated temporary objects as seen in the source program is less than, but not easy to detect, and therefore need to focus on.

(4) function call

Since the function call overhead is fixed, so that when the function code amount thereof is relatively small, and very often when the function is called, the function call overhead fixed easily become unnecessary overhead. Wang C language and C ++ language inline functions are fixed to eliminate the overhead of a function call in the modular nature of the function calls on the basis of maintaining introduced. Since the C language macros but also to the development and debugging inconvenience in ××× energy advantages, and therefore recommend the use of the C ++ language inline function.

Second, the constructor and destructor

1, the constructor and destructor Introduction

Features constructor and destructor is automatically executed when creating an object constructor; when the object is destroyed, the destructor is automatically executed. A constructor is a function of an object to be executed first, when the call to create the object, the initial state of the object to initialize and access some resources used before the desired object, such as files, network connections; destructor of an object is the last function is executed, the objects have the resources for release. In the lifetime of the object, the constructor and destructor are executed only once.

Create an object in two ways, one is created from a thread running stack, called local objects. Local objects are destroyed does not need to display the program calls the destructor, but when the program runs out of scope of the object belongs destructor is automatically invoked object.

Another way is to create objects dynamically allocated from the global heap, usually new or malloc allocate heap space.

Obejct* p = new Object();//1
// do something //2
delete p;//3
p = NULL;//4

When a statement is executed, the pointer p pointing object is obtained from the global memory heap space, and the address assigned to p, p itself is a local variable, needs to be allocated from the thread stack, p is the pointing object from the global heap memory allocated storage. From the global heap objects created for destruction to be displayed call delete, delete calls the destructor pointer p points to an object, and the global heap memory space occupied by the object is returned to the global heap. After executing a statement 3, the pointer p points to an object is destroyed, but the pointer p is also present in the stack until the program exits in its scope. After the destruction of the object pointed to by p, p pointer still points to the global heap space position of the object is destroyed, then the pointer p becomes a dangling pointer, this time using the pointer p is dangerous, usually recommended p assignment NULL.

In the Win32 platform, accessing the global destruction of objects heap memory space can lead to three situations:

(1) memory pages to be destroyed where the object is no object, the heap manager has the further recovery of the operating system heap space occupied, this time by accessing pointers can cause an access violation, namely the illegal memory access, causing the process to crash.

(2) memory pages are destroying objects where the presence of other objects, and the object is destroyed once occupied by the global heap space after being recovered has not been assigned to other objects, this time by taking the value of the pointer p access is meaningless, though not immediately caused a crash course, but for the subsequent operating behavior pointer p is unpredictable.

(3) where the object is destroyed memory page there are other objects, and the object is destroyed once occupied space after being recovered global heap has been allocated to other objects, this time by the value of the pointer p other objects are achieved, although pointer p access will not cause the collapse of the process, but is likely to cause a change in state of an object.

2, the configuration of process objects

Create an object is divided into two steps, first obtain the desired object memory (the heap from the thread stack or global), and then execute the constructor in the memory space. When building object constructor, the constructor is also divided into two steps. The first step in initialization is performed, the second step is performed body of the constructor (initialization parameter list).

class Derived : public Base
{
public:
    Derived(): id(1), name("UnNamed")   // 1
    {
        // do something     // 2
    }
private:
    int id;
    string name;
};

Code statements in the colon is the initialization list 1, each cell is initialized mode name (value) of the variable, separated by commas between different units. Constructor first performs initialization according to the initialization list, and then execute the body of the constructor (statement 2). Note the initialization operation is as follows:

(1) The constructor is actually a recursive operation, an operation in the interior of each recursive follow a strict order. Recursive mode is performed first constructor parent class (parent class constructor operation accordingly comprises two portions executed performs initialization and constructor body), the parent class constructor returns variable configuration member of the class itself. When constructing their own class member variables, one is in strict accordance member variables in a class declaration order, and the order of appearance in the member variable initialization list has nothing to do; the second is when some members of the parent object or variable does not appear in the initialization list when, still in the initialization operation to initialize, built-in type member variable is assigned to an initial value, and the parent object class member variable objects is calling its default constructor initializes, then the constructor and child objects of the parent class member variables during the execution of the constructor also follow the above recursion, member variables of the class inheritance hierarchy until all the parent classes and parent classes are contained in the completion of construction, class initialization operation to complete.

(2) the parent object and a number of member variables in the initialization list does not appear, it will still be executed default constructor. Thus, the object's class must provide the appropriate default constructor may call, for which the corresponding class requirements must explicitly provide a default constructor, or can not prevent the compiler generates a default constructor is implicitly defined default constructor in addition to other types of outer the constructor will prevent the compiler-generated default constructor. If the compiler at compile time, find that the default constructor is not called for, and the compiler can not generate a default constructor, the compiler can not.

(3) two types of member variables, it is necessary to emphasize that (ie, constant reference type and type). Since all members of the variable has been configured, i.e., before executing the function already has an initial value thereof, therefore, for a constant and a reference type variable must be properly initialized in the initialization list it, but not in the constructor initializes vivo.

(4) the initialization list may not be a complete list of its child members or members of the parent object, or a different order of its declaration in the class will still be fully and strictly ensure strict order is built. I.e. the constructor procedure before entering the body, the parent object class member variables and all child objects have been generated and configured. If the execution of its assignment in the constructor body, apparently belonging to waste. If in the constructor already know how to initialize a sub-member variable of the class, you should initialize the information given by the constructor initializer list of child members variable, not initialized in the constructor body, because getting into the constructor, the child member variables It has been initialized once.

3, the process of destruction of the object

Constructor and destructor, is a recursive process, but there are different. One part of the initialization operation destructor, destructor major work is performed destructor function body does not exist; two opposite recursive constructor destructor performed, each layer recursion, the object member variable destructor be reversed sequence constructor.

Destructor only class member variables selected reference (positive sequence or reverse) in the order as the order of class declared destructor. Since the positive sequence selected constructor, but rather work destructor constructor, destructor thus select reverse. And because destructor member variables can only be used in the class declaration order as the basis destructor sequence (positive sequence or reverse), and therefore can only select the constructor in the class member variable declaration order as the order of the number of configuration, the order can not be used as the initialization list according to the order.

If the object operation end nodes belong to a system of complex inheritance, its destructor will be very time-consuming process.

In C ++ programs, creating and destroying objects affect the performance of a very prominent operation. First, if the object is generated from the global heap space, the need for dynamic memory allocation operation, the dynamic memory allocation and recovery is very time-consuming operation, because it involves seeking to match the size of the memory block may also need to find the truncation process, then also need to modify the list to maintain global heap memory usage information. Frequent memory operation will seriously affect the performance degradation, use memory pool technology can reduce the number of applications from the global dynamic heap memory space, improve the overall performance of the program. When the acquisition memory, if necessary to generate the object belongs to a class of complex inheritance hierarchy terminal, constructor is called recursive construction will cause a series of operations, in large complex systems, a large number of such objects will consume CPU configuration operating the main sections.

Since the object creation and destruction will affect the performance, minimize their own code generation target at the same time, we need to focus on objects at compile time the compiler generates a temporary, try to avoid the formation of temporary objects.

If the constructor when implemented, perform a second assignment in the constructor of the body, it is also a waste of CPU time.

4, transfer function parameters

A common method of reducing object creation and destruction are all passed by value instead constants in the declaration passed by reference, such as:

int func(Object obj);// 1
int func(const Object& obj);// 2

Value passed validation example as follows:

#include <iostream>

using namespace std;

class Object
{
public:
    Object(int i = 1)
    {
        n = i;
        cout << "Object(int i = 1): " << endl;
    }
    Object(const Object& another)
    {
        n = another.n;
        cout << "Object(const Object& another): " << endl;
    }
    void increase()
    {
        n++;
    }
    int value()const
    {
        return n;
    }
    ~Object()
    {
        cout << "~Object()" << endl;
    }
private:
    int n;
};
void func(Object obj)
{
    cout << "enter func, before increase(), n = " << obj.value() << endl;
    obj.increase();
    cout << "enter func, after increase(), n = " << obj.value() << endl;
}
int main()
{
    Object a;   // 1
    cout << "before call func, n = " << a.value() << endl;
    func(a);    // 2
    cout << "after call func, n = " << a.value() << endl;// 3

    return 0;
}
// output:
//Object(int i = 1):        // 4
//before call func, n = 1
//Object(const Object& another):    // 5
//enter func, before increase(), n = 1  // 6
//enter func, after increase(), n = 2   // 7
//~Object() // 8
//after call func, n = 1    // 9
//~Object()

4 is a target output statement structure 1 at the statement, the statement is output FUNC 5 (a) at a function call statement 2, generated when calling the object is started by a copy constructor copies, followed by the check function of n the output value of the output statement 6, the same output value, and a function func external element object, and then calls the copy function increase the value of n plus 1, then a value of 2 n replicas, and output statement 7. func function after the implementation of the destruction of copies, output statements 8. Continue the main function of a print original target value of n is 1, the output statement 9.

When the need to modify the function parameter passing, it should be passed by reference parameter; when the function does not modify the incoming parameters, if a function declaration passed in parameter is an object, the function can be designed to achieve, but it will generate unnecessary replication target products, thereby introducing unnecessary construction and destruction operations, reference should be passed using a constant parameter.

Repeat assignment constructor impact on performance verification examples are as follows:

#include <iostream>
#include <time.h>

using namespace std;

class DArray
{
public:
    DArray(double v = 1.0)
    {
        for(int i = 0; i < 1000; i++)
        {
            d[i] = v + i;
        }
    }
    void init(double v = 1.0)
    {
        for(int i = 0; i < 1000; i++)
        {
            d[i] = v + i;
        }
    }
private:
    double d[1000];
};

class Object
{
public:
    Object(double v)
    {
        d.init(v);
    }
private:
    DArray d;
};

int main()
{
    clock_t start, finish;
    start = clock();
    for(int i = 0; i < 100000; i++)
    {
        Object obj(2.0 + i);
    }
    finish = clock();
    cout << "Used Time: " << double(finish - start) << "" << endl;

    return 0;
}

Consuming 600,000 units, if the member variable is initialized by the initialization list, its code is as follows:

#include <iostream>
#include <time.h>

using namespace std;

class DArray
{
public:
    DArray(double v = 1.0)
    {
        for(int i = 0; i < 1000; i++)
        {
            d[i] = v + i;
        }
    }
    void init(double v = 1.0)
    {
        for(int i = 0; i < 1000; i++)
        {
            d[i] = v + i;
        }
    }
private:
    double d[1000];
};

class Object
{
public:
    Object(double v): d(v)
    {
    }
private:
    DArray d;
};

int main()
{
    clock_t start, finish;
    start = clock();
    for(int i = 0; i < 100000; i++)
    {
        Object obj(2.0 + i);
    }
    finish = clock();
    cout << "Used Time: " << double(finish - start) << "" << endl;

    return 0;
}

Consuming 300,000 units, performance is improved by about 50%.

Third, inheritance and virtual functions

1, virtual functions and dynamic binding mechanism

Virtual function is an important feature introduced in C ++ language provides a dynamic binding mechanism, such that the dynamic binding mechanism semantic class inherits becomes relatively clear.

(1) the general abstract base class data and operations. For the data, if the data members in each derived class needs to use, it needs to be declared in the base class; for operation language, if the operator has a meaning for each derived class, regardless of whether it will be modified and semantics expansion, needs to be declared in the base class.

(2) certain operations, for each derived class, the complete semantic consistency, and extended without having to modify, the corresponding operation is declared non-virtual base class member function. Each derived class declaration is a class derived from the base, and a default statement implementation inheritance non-virtual member function, if the default base class data members inherited as, without making any additional statements constituting code reuse.

(3) For some operations, although each have meaning for the derived class, but the semantics are not identical, the operation should be declared as corresponding to virtual member functions. Although each derived class also inherits the declaration and implementation of virtual member functions, but semantically should implement virtual member functions are modified or extended. If the process of implementing the modification, extension, virtual member function in the derived class need to use additional unique data, the corresponding data is declared as a derived class of their own data members.

When the higher-level framework (inherited user system) Use this inheritance system, dealing with the level of abstraction of a collection of objects, a member of the nature of the object is a collection of various derived class object, but the object in the process of collection of objects, the use a level of abstraction of the operation. Does not distinguish between high-level application framework in which the operation corresponding to the operation is the same derived class, the derived class to which the operation is different, when the actual execution of each operation, the runtime system is able to identify which operations need to use dynamic binding. To find modified or extended release operation corresponding to the derived class. That inheritance hierarchy of the user in terms of diversity within the inheritance system is transparent and does not have to be concerned about the details of its successor, the process is a set of user behavior in terms consistent with the overall target. Even if the internal inheritance system increases, delete a derived class, or a derived class virtual function to achieve changed, users do not have to make any changes to the code, the modularity of the program has been greatly improved, and its scalability , code readability and maintainability will be improved. For objects inherit system users, only to see the abstract type without having to be concerned about specifically what specific type.

If you have wanted to learn c ++ programmers, you can come to our C / C ++ learning buckle qun: 589348389,
free delivery C ++ Video Tutorial Oh!
Each 20:00 I will live in the group to explain the C / C ++ knowledge, welcome everyone to learn Oh.
 

Guess you like

Origin blog.csdn.net/XZQ121963/article/details/91431758