测试_第24章_性能优化.cpp

← 测试总览 · 目录

编译运行: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;
}