C++性能优化

类或者结构体常用数据前置

结构体数据不要嵌套太深,因为每一级的嵌套都意味着一次的寻址
相关的数据放到一起,提升数据的耦合性,提高访问效率
常用数据前置,以免导致页交换等

1
2
3
4
5
struct compact{
int a;
int b;
int c[10000];
}

几种构造函数

默认构造函数
初始化构造函数
拷贝构造函数
赋值构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
struct MyData {
MyData() { cout << "Default Construct" << endl;}
MyData(const MyData& rhs) {cout << "Copy Construct" << endl;}
MyData& operator=(const MyData& rhs) {cout << "Assign Construct" << endl; return *this;}
};

class MyType {
public:
MyType(MyData data) {
_data = data;
cout << "MyType constructor" << endl;
}
MyData _data;
};

class MyType1 {
public:
MyType1(MyData& data) {
_data = data;
cout << "MyType1 constructor" << endl;
}
MyData _data;
};

class MyType2 {
public:
MyType2(MyData& data) : _data(data) {
cout << "MyType2 constructor" << endl;
}
MyData _data;
};

int main()
{
MyData data;
cout << "========================" << endl;
MyType type(data);
cout << "========================" << endl;
MyType1 type1(data);
cout << "========================" << endl;
MyType2 type2(data);
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
Default Construct
========================
Copy Construct
Default Construct
Assign Construct
MyType constructor
========================
Default Construct
Assign Construct
MyType1 constructor
========================
Copy Construct
MyType2 constructor

类成员的初始化放到初始化列表中

1
2
3
4
5
6
7
class MyType2 {
public:
MyType2(MyData& data) : _data(data) {
cout << "MyType2 constructor" << endl;
}
MyData _data;
};

内存相关的优化

  • 尽量使用栈内存,少用堆内存

    堆内存是new出来的,慢,且容易产生碎片
    堆内存也更容易被操作系统给交换到外存中。

  • 引用传参
  • placement new

    • new不能被重载,它先调用operator new分配内存,然后调用构造函数初始化那段内存
    • operator new 要实现不同的内存分配行为,需要重载operator new, 而不是new
    • placement new是operator new的一个重载版本,它不分配内存,只是返回只想已经分配好的某段内存的一个指针,因此不能删除它,只能调用对象的析构函数。placement new重用了已有的内存,没有频繁的内存申请和释放,提升了性能,减轻了碎片化。
1
2
3
4
5
6
7
void testPlacementNew() {
unsigned char buf[sizeof(int) * 2];
for (int i = 0; i < 100000; ++i) {
ComplexType* ct = new (buf) ComplexType();
reinterpret_cast<ComplexType*>(buf)->~ComplexType();
}
}

循环优化

++iter 相比于iter++ 会少一步指令

外小内大

二维数组是按行存储的。如果一行存储的数据超过了数据分页,那么按列访问就会导致频繁的跨页访问。
连续访问的数据比跳页访问要快
外小内大的方式还能节约内存,因为页面交换的时候可能需要额外的内存来帮助

1
2
3
4
5
6
7
8
void testSmallbig(){
double data[100][10000];
for (int i = 0; i < 100; i++) {
for (int j = 0; j < 10000; j++) {
data[i][j] = i * j;
}
}
}

C++ 新特性的性能优化

右值引用和移动语义

减少两个对象交互时的不必要copy

1
2
3
4
5
6
7
8
9
void test() {
vector<int> vs;
vs.resize(100000);
for (auto v : s) {
v = v + 1;
}
vector<int> vs1 = vs;
vector<int> vs2 = std::move(vs);
}

使用前提:

  • 定义的类使用了资源并定义了移动构造函数和移动赋值运算符
  • 该变量即将不再使用

unordered_map

make_shared

1
2
std::shared_ptr<Data> spw(new Data);
auto spw = std::make_shared<Data>();

final

constexpr

编译期计算

容器选择

vector > deque > list/forward_list

qsort比sort快

编译器优化

  • 短小函数inline化
  • PGO
显示 Gitment 评论