C/C++开发者代码优化终极指南

优化意味着调整代码,使 CPU、内存子系统和编译器能够高效执行

引言

优化意味着调整代码,使 CPU、内存子系统和编译器能够高效执行——不改变逻辑,而是减少运行所需的周期、分配和停顿。

🎯 核心目标:让代码跑得更快、占用更少内存、响应更及时!


核心优化策略

1. 减少执行时间

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// ❌ 每次调用都计算
for (int i = 0; i < N; ++i) {
double angle = i * 2 * M_PI / N; // 每次计算
result[i] = std::sin(angle);
}

// ✅ 预计算常量
const double TWO_PI = 2 * M_PI;
for (int i = 0; i < N; ++i) {
double angle = i * TWO_PI / N; // 使用常量
result[i] = std::sin(angle);
}

// ✅ 更好的方式:查表法
static const double sin_table[N] = { /* 预计算的值 */ };
for (int i = 0; i < N; ++i) {
result[i] = sin_table[i]; // 直接查表
}

2. 最小化内存使用

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
// ❌ 重复重分配
std::vector<Data> collectData() {
std::vector<Data> result;
for (auto& input : inputs) {
result.push_back(process(input)); // 多次重分配
}
return result;
}

// ✅ 预分配容量
std::vector<Data> collectData() {
std::vector<Data> result;
result.reserve(inputs.size()); // 预分配
for (auto& input : inputs) {
result.push_back(process(input));
}
return result;
}

// ✅ 移动语义
std::vector<Data> collectData() {
std::vector<Data> result;
result.reserve(inputs.size());
for (auto& input : inputs) {
result.emplace_back(process(input)); // 原地构造
}
return result;
}

3. 移除循环中的动态分配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// ❌ 循环内分配
void processLoop(std::vector<Item>& items) {
for (auto& item : items) {
std::string key = item.name; // 每次分配
cache[key] = compute(item);
}
}

// ✅ 循环外分配/引用
void processLoop(std::vector<Item>& items) {
std::string key; // 循环外分配
for (auto& item : items) {
key = item.name; // 复用
cache[key] = compute(item);
}
}

FFT 优化案例

问题分析

原始 FFT 实现性能灾难性,原因是:

  • ❌ 跨数组的跳转内存访问
  • ❌ 重复三角计算
  • ❌ 分量数组布局破坏空间局部性

优化方案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 优化前:重复计算 twiddle 因子
std::complex<double> twiddle(int k, int N) {
return std::exp(std::complex<double>(0, -2 * M_PI * k / N)); // 每次计算
}

// 优化后:预计算 twiddle 因子
class FFT {
std::vector<std::complex<double>> twiddle_factors;

public:
FFT(int N) {
twiddle_factors.resize(N);
for (int k = 0; k < N; ++k) {
twiddle_factors[k] = std::exp(std::complex<double>(0, -2 * M_PI * k / N));
}
}

const std::complex<double>& twiddle(int k) const {
return twiddle_factors[k];
}
};

性能提升

优化项 提升
预计算 twiddle 因子 3-5x
内存布局优化 2-3x
SIMD 向量化 2-4x
总计 10-30x

嵌入式系统优化

实时系统要求

现代嵌入式设备必须在有限硬件上处理复杂工作负载。优化对于确保:

  • 确定性执行 - 任务完成时间可预测
  • 减少抖动 - 最小化时间波动
  • 最小化内存 - 避免堆碎片

固定缓冲区 vs 动态分配

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ❌ 实时系统中的动态分配
class SensorProcessor {
std::vector<double> buffer; // 动态分配

public:
void process() {
buffer.resize(getSampleCount()); // 运行时分配!
}
};

// ✅ 使用固定缓冲区
class SensorProcessor {
static constexpr size_t MAX_SAMPLES = 1024;
double buffer[MAX_SAMPLES]; // 栈上固定分配

public:
void process() {
size_t count = getSampleCount();
assert(count <= MAX_SAMPLES);
// 直接使用固定缓冲区
}
};

性能优化检查清单

代码层面

  • 移除循环中的冗余操作
  • 避免循环内的函数调用
  • 使用移动语义避免拷贝
  • 预分配容器容量
  • 避免不必要的类型转换

架构层面

  • 数据对齐到缓存行
  • 避免伪共享
  • 使用内存池
  • 考虑 SIMD 向量化
  • 异步 I/O vs 同步 I/O

总结

💡 黄金法则先测量,再优化!

  1. 使用 profiler 定位瓶颈
  2. 理解代码的数据访问模式
  3. 优化热点路径
  4. 验证优化效果

本文档基于 WedoLow 代码优化指南扩展而成