编译运行:clang++ -std=c++26 -Wall -Wextra -pthread 测试_第24章_性能优化.cpp -o t && ./t(需先 cd 测试/)
// 第24章测试:性能优化(可测量的对比实验)
// 注意:以下所有对比都是"教育演示",真实项目请用 profiler 找热点
#include <print>
#include <chrono>
#include <vector>
#include <unordered_set>
#include <string>
#include <numeric>
#include <random>
int failures = 0;
#define CHECK(expr) \
do { \
if (!(expr)) { \
++failures; \
std::println("FAIL 第{}行: {}", __LINE__, #expr); \
} \
} while (0)
template <typename F>
double bench_ms(const char* name, F&& f) {
auto start = std::chrono::steady_clock::now();
f();
auto end = std::chrono::steady_clock::now();
double ms = std::chrono::duration<double, std::milli>(end - start).count();
std::println("{:<28} {:>10.2f} ms", name, ms);
return ms;
}
int main() {
constexpr int N = 4096;
// ============ 实验1:矩阵遍历顺序 ============
std::vector<int> matrix(N * N, 1);
std::println("\n--- 实验1:矩阵遍历(4096x4096,行优先存储)---");
// 行优先遍历(连续访问,缓存友好)
auto row_major = bench_ms("行优先遍历", [&] {
volatile long long s = 0;
for (int i = 0; i < N; ++i)
for (int j = 0; j < N; ++j) s += matrix[i * N + j];
});
// 列优先遍历(跳跃访问,缓存不友好)
auto col_major = bench_ms("列优先遍历", [&] {
volatile long long s = 0;
for (int j = 0; j < N; ++j)
for (int i = 0; i < N; ++i) s += matrix[i * N + j];
});
CHECK(col_major > row_major);
std::println("列优先是行优先的 {:.1f} 倍", col_major / row_major);
// ============ 实验2:查找优化 ============
std::println("\n--- 实验2:100 万数据中查 1 万个随机数 ---");
constexpr int M = 1'000'000, Q = 10'000;
std::vector<int> data(M);
std::iota(data.begin(), data.end(), 0);
std::mt19937 rng(42);
std::uniform_int_distribution<int> dist(0, M - 1);
std::vector<int> queries(Q);
for (auto& q : queries) q = dist(rng);
// 线性查找 O(n·q)
auto lin_find = bench_ms("vector 线性查找", [&] {
int hits = 0;
for (int q : queries)
if (std::find(data.begin(), data.end(), q) != data.end()) ++hits;
CHECK(hits == Q);
});
// 哈希集合查找 O(q)
std::unordered_set<int> set(data.begin(), data.end());
auto hash_find = bench_ms("unordered_set 查找", [&] {
int hits = 0;
for (int q : queries)
if (set.contains(q)) ++hits;
CHECK(hits == Q);
});
CHECK(hash_find < lin_find);
std::println("哈希查找比线性快 {:.0f} 倍", lin_find / hash_find);
// ============ 实验3:字符串拼接 ============
std::println("\n--- 实验3:拼接 5 万个短字符串 ---");
constexpr int SN = 50'000;
auto str_naive = bench_ms("+= 朴素拼接", [&] {
std::string s;
for (int i = 0; i < SN; ++i) s += std::to_string(i);
CHECK(s.size() > SN);
});
auto str_reserve = bench_ms("reserve + append", [&] {
std::string s;
s.reserve(SN * 8); // 预分配,避免反复扩容
for (int i = 0; i < SN; ++i) s += std::to_string(i);
CHECK(s.size() > SN);
});
std::println("reserve 快 {:.1f} 倍", str_naive / str_reserve);
// ============ 实验4:编译期查表 vs 运行期计算 ============
std::println("\n--- 实验4:编译期查表 vs 运行期计算(仅验证正确性)---");
constexpr int table[10] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81};
for (int i = 0; i < 10; ++i) CHECK(table[i] == i * i);
// ============ 实验5:reserve 对 push_back 的影响 ============
std::println("\n--- 实验5:vector 扩容(10 万次 push_back)---");
auto pb_naive = bench_ms("无 reserve push_back", [&] {
std::vector<int> v;
for (int i = 0; i < 100'000; ++i) v.push_back(i);
CHECK(v.size() == 100'000);
});
auto pb_reserve = bench_ms("reserve 后 push_back", [&] {
std::vector<int> v;
v.reserve(100'000);
for (int i = 0; i < 100'000; ++i) v.push_back(i);
CHECK(v.size() == 100'000);
});
std::println("reserve 快 {:.1f} 倍", pb_naive / pb_reserve);
if (failures == 0) std::println("\n全部通过");
return failures;
}