Skip to content

第一百九十章:性能优化

大乘期

涉及内核源码:

数据中心的最深处,林小源来到一间密室。密室的墙壁上挂满了火焰图——红色的色块高低起伏,如同燃烧的山峦。

一位精瘦的老者站在火焰图前,手持放大镜,仔细端详着每一处细节。

"前辈在看什么?"

"性能热点。"老者没有回头,"我是性能优化的守护者。perf、ftrace、火焰图——这些工具能告诉你,CPU的时间都花在了哪里。找到热点,才能优化。"

他放下放大镜,转向林小源。"性能优化不是玄学,是科学。第一步,测量;第二步,找到瓶颈;第三步,优化;第四步,再测量。没有测量的优化是盲目的。"

"前辈,有哪些优化手段?"

老者走到一张工作台前,台上摆满了各种工具。"缓存优化——数据对齐到缓存行边界,避免false sharing。分支预测——用likely/unlikely告诉CPU哪条路径更可能执行。内联函数——减少函数调用的开销。"

老者拿起一个透明的容器,里面装着一段数据流。"零拷贝。传统的数据传输需要多次拷贝——从磁盘到内核缓冲区,从内核缓冲区到用户空间,再从用户空间到网络缓冲区。sendfile和splice绕过了这些拷贝,让数据直接从文件缓冲区流向网络缓冲区。"

"这能省多少?"

"在高吞吐的网络服务器上,零拷贝可以省掉30%以上的CPU时间。"老者将容器放回台上,"内核中还有许多类似的优化:批处理——把多个操作合并成一次,减少系统调用和中断的开销;延迟处理——中断下半部,把不紧急的工作推迟到稍后处理。"

"前辈,SIMD呢?"林小源问道。

老者从抽屉中取出一枚特殊的水晶,水晶中闪烁着四个并排的数字。"SIMD——单指令多数据。一条指令同时处理四个、八个甚至十六个数据。内核中的crypto子系统、网络校验和计算,都用SIMD加速。"

他将水晶举到灯光下。"但SIMD有约束——数据必须对齐,算法必须能向量化。不是所有计算都适合SIMD。"

老者收起水晶,语重心长地说:"性能优化是一门艺术。它需要对硬件的深刻理解,对算法的精准把握,对数据的敏锐嗅觉。记住,过早优化是万恶之源——先让代码正确,再让它快。"

c
/*
 * 内核性能优化:
 *
 * 1. 缓存优化
 *    数据对齐
 *    缓存行填充
 *    减少缓存颠簸
 *
 * 2. 分支预测
 *    likely/unlikely
 *    帮助 CPU 预测
 *
 * 3. 内联函数
 *    inline
 *    减少函数调用开销
 *
 * 4. Per-CPU 数据
 *    避免锁竞争
 *
 * 5. 批处理
 *    减少操作次数
 *
 * 6. 延迟处理
 *    中断下半部
 *    工作队列
 *
 * 7. 零拷贝
 *    sendfile
 *    splice
 *
 * 8. SIMD
 *    向量化指令
 */

/* 缓存优化 */
struct __attribute__((aligned(64))) cache_aligned {
    int data;
    char padding[60]; /* 填充到 64 字节 */
};

/* 分支预测优化 */
#define likely(x)   __builtin_expect(!!(x), 1)
#define unlikely(x) __builtin_expect(!!(x), 0)

int process(int val) {
    if (likely(val > 0)) {
        /* 常见路径 */
        return val * 2;
    } else {
        /* 罕见路径 */
        return 0;
    }
}

/* 内联函数 */
static inline int fast_add(int a, int b) {
    return a + b;
}

printf("=== 性能优化 — 让系统更快 ===\n\n");

/* 缓存优化 */
printf("--- 缓存优化 ---\n");
printf("普通结构体大小: %zu\n", sizeof(int));
printf("缓存对齐结构体大小: %zu\n", sizeof(struct cache_aligned));
printf("缓存行大小: 64 字节\n\n");

/* 分支预测 */
printf("--- 分支预测 ---\n");
int result = process(10);
printf("process(10) = %d\n", result);
printf("likely/unlikely 帮助 CPU 预测\n\n");

/* 内联函数 */
printf("--- 内联函数 ---\n");
int sum = fast_add(3, 4);
printf("fast_add(3, 4) = %d\n", sum);
printf("inline 减少函数调用开销\n\n");

printf("--- 优化技术 ---\n");
printf("1. 缓存优化:\n");
printf("   数据对齐\n");
printf("   缓存行填充\n");
printf("   减少缓存颠簸\n\n");
printf("2. 分支预测:\n");
printf("   likely/unlikely\n");
printf("   帮助 CPU 预测\n\n");
printf("3. 内联函数:\n");
printf("   inline\n");
printf("   减少函数调用开销\n\n");
printf("4. Per-CPU 数据:\n");
printf("   避免锁竞争\n\n");
printf("5. 批处理:\n");
printf("   减少操作次数\n\n");
printf("6. 延迟处理:\n");
printf("   中断下半部\n");
printf("   工作队列\n\n");
printf("7. 零拷贝:\n");
printf("   sendfile\n");
printf("   splice\n\n");
printf("8. SIMD:\n");
printf("   向量化指令\n");
printf("   加速计算\n\n");

printf("--- 性能分析工具 ---\n");
printf("perf:\n");
printf("   性能计数器\n");
printf("   采样分析\n\n");
printf("ftrace:\n");
printf("   函数跟踪\n\n");
printf("火焰图:\n");
printf("   可视化性能热点\n");

道藏笔记

内核启示

性能优化让系统更快更高效。

优化技术:

  • 缓存优化 — 数据对齐、缓存行填充
  • 分支预测 — likely/unlikely
  • 内联函数 — 减少调用开销
  • Per-CPU — 避免锁竞争
  • 批处理 — 减少操作次数
  • 延迟处理 — 中断下半部
  • 零拷贝 — sendfile
  • SIMD — 向量化指令

性能分析:

  • perf — 性能计数器
  • ftrace — 函数跟踪
  • 火焰图 — 可视化热点

性能优化是艺术——在细节中寻找提升。


破关试炼

性能优化之试

性能优化中,单条指令处理多份数据的向量化技术缩写是什么?

答对后才能继续滑动和进入下一章。

以修仙之名,悟内核之道