用于性能分析的 CPU 特性

性能分析(performance analysis)的最终目标是识别性能瓶颈,并定位与之相关的代码部分。遗憾的是,这一过程没有固定的步骤可循,因此可以从多种不同角度入手。

通常,对应用程序进行性能剖析(profiling)可以快速了解其热点(hotspot)所在。有时,这已经足以帮助开发者发现并修复性能问题。高层次的性能问题尤其容易通过剖析暴露出来。例如,假设你刚刚修改了应用程序中的函数 foo,随后发现性能出现了明显下降。于是你决定对应用程序进行剖析。根据你对应用程序的认知,你预期 foo 是一个冷函数,不会出现在热点函数前十名中。但当你打开剖析结果时,却发现它消耗的时间比以前多得多。你很快意识到自己在代码中犯了错误并加以修复。如果性能工程中所有问题都这么容易解决,这本书就没有存在的必要了。

当你踏上榨取应用程序最后一点性能的征程时,仅仅查看热点列表是远远不够的。除非你有一个水晶球,或者脑海中有整个 CPU 的精确模型,否则你需要额外的支持来理解性能瓶颈究竟在哪里。

一些开发者依赖直觉,随机尝试各种编译器优化,比如循环展开(loop unrolling)、向量化(vectorization)、内联(inlining)等等。的确,有时候你可能运气不错,赢得同事的称赞,甚至被奉为团队中非官方的性能大师。但通常情况下,你需要有非常好的直觉和运气。本书不会教你如何变得幸运,而是展示那些在实践中被证明有效的方法。

现代 CPU 不断引入新特性,从不同维度增强性能分析能力。利用这些特性,可以大大简化发现底层问题(如缓存缺失(cache miss)、分支预测错误(branch misprediction)等)的过程。在本章中,我们将介绍现代 CPU 上可用的几种硬件性能监控能力。不同厂商的处理器不一定具备相同的特性集。我们将探讨 Intel、AMD 和 Arm 处理器中可用的性能监控能力。1

  • 自顶向下微架构分析(Top-down Microarchitecture Analysis,TMA)方法论,在 [TMA] 中讨论。这是一种用于识别程序对 CPU 微架构(microarchitecture)低效使用的强大技术。它能够描述工作负载的瓶颈特征,并精确定位到源代码中发生瓶颈的位置。它将 CPU 微架构的复杂细节抽象化,即使是经验不足的开发者也相对容易上手。
  • 分支记录(Branch Recording),在 [lbr] 中讨论。这是一种在程序执行的同时持续记录最近分支结果的机制。它被用于收集调用栈(call stack)、识别热分支(hot branch)、计算单个分支的预测错误率等。
  • 基于硬件的采样(Hardware-Based Sampling),在 [secPEBS] 中讨论。这是一种增强采样的特性。其主要优势包括:降低采样开销,以及提供"精确事件"(Precise Events)能力,从而能够精确定位导致特定性能事件的指令。
  • Intel 处理器追踪(Intel Processor Traces,PT),在附录 C 中讨论。这是一种用于记录和重建程序执行过程的设施,可以对每条指令附加时间戳。其主要用途是事后分析(postmortem analysis)和追溯性能故障的根因。

Intel PT 特性在附录 C 中介绍。Intel PT 本应成为性能分析的"终极武器"。凭借其较低的运行时开销,它是一个非常强大的分析特性。但实际上,它在性能工程师中并不十分流行。部分原因是工具支持尚不成熟,部分原因是在许多情况下它过于强大,使用采样剖析器反而更简便。此外,它会产生大量数据,对于长时间运行的工作负载而言并不实用。尽管如此,它在某些行业(如高频交易(high-frequency trading,HFT))中依然颇为流行。

上述硬件性能监控特性从 CPU 视角提供了对程序效率的洞察。在下一章中,我们将讨论性能剖析工具如何利用这些特性来支持多种不同类型的分析。

1. RISC-V 生态系统目前尚未具备成熟的性能监控基础设施,因此本书不会涵盖相关内容。

results matching ""

    No results matching ""