(1) Trace 和调试器

程序执行 = 状态机执行

  • 我们能不能 “hack” 进这个状态机
    • 观察状态机的执行
      • strace/gdb
    • 甚至记录和改变状态机的执行

Time-Travel Debugging & Record-replay

  • 如何退回到 $ s_0 \to s_1 \to s_2 \to \ldots $ 中的任何一个状态?
    • AskGPT: How is time-travel debugging implemented in gdb?
  • 我们甚至可以完整记录程序的执行
    • rr, QEMU, ...

(2) 性能优化和 Profiler

Premature optimization is the root of all evil. (D. E. Knuth)

那到底怎么样才算 mature 呢?

  • 状态机的执行需要时间;对象需要占用空间
  • 需要理解好 “时间花在哪里”、“什么对象占用了空间”

我们需要真实执行的性能摘要

  • 本质的回答:“为了做某件事到底花去了多少资源”
  • 简化的回答:“一段时间内资源的消耗情况”

Profiler 和性能摘要

隔一段时间 “暂停” 程序、观察状态机的执行

  • 中断就可以做到
  • 将状态 $s \to s'$ “记账”
    • 执行的语句
    • 函数调用栈
    • 服务的请求
  • 得到统计意义的性能摘要

例子:Linux Kernel perf (支持硬件 PMU)

  • perf list, perf stat (-e), perf record, perf report
  • 案例:如果你部署了 100 台一模一样的机器,但有一台 CPU 100%,应该怎么办?

实际中的性能优化

你们遇到的大部分情况

  • 二八定律:80% 的时间消耗在非常集中的几处代码
  • L1 (pmm): 小内存分配时的 lock contention
    • profiler 直接帮你解决问题

工业界遇到的大部分情况

  • 木桶效应:每个部分都已经 tune 到局部最优了
    • 剩下的部分要么 profiler 信息不完整,要么就不好解决
    • (工程师整天都对着 profiler 看得头都大了)
    • The flame graph (CACM'16)

(3) Model Checker 和 Verifier

一些真正的 model checkers


任何 “non-deterministic” 的状态机都可以检查

u32 x = rdrand(), y = rdrand();
if (x > y)
  if (x * x + y * y == 65)
    bug();  // 如何有效地检验?