多年前,在上一家公司参与某编译器项目时,为了度量编译器生成汇编指令的效率,我曾经尝试过基于控制流图(Control Flow Graph,CFG)模拟计算某个Java函数包含的汇编指令运行所需的总时钟周期数。虽然这是一种粗略的静态计算方法,跟CPU的真实运行场景有相当大的差别,但却在我心里种下了进一步了解指令在CPU内部究竟如何运行的种子。
后来,到新公司工作后,我开始整体负责虚拟机和编译优化相关业务,苦苦探索用于分析和度量程序性能的方法,以判断某段程序是否可以进行编译优化,以及可用何种方法进行优化。我们注意到了Intel在x86平台上的自顶向下微架构性能分析方法,但是相关论文中有大量的术语和背景知识,如架构、微架构、流水线、前后端、翻译后备缓冲区(Translation Lookaside Buffer,TLB)等,理解起来非常困难。在网上搜索相关资料时,大部分都是碎片化的信息,对从整体上全面理解自顶向下分析方法并不能提供太大的帮助。
就在我们苦苦探索时,偶然在微信公众号“Linux阅码场”上看到一篇文章推荐了两本书,其中一本是Brendan Gregg的《性能之巅》,另一本就是来自Denis Bakhvalov的 Performance Analysis and Tuning on Modern CPUs 。我们瞬间就被目录中的内容吸引了,这不就是我们正在追寻的东西吗?于是,我们便一头扎了进去,如饥似渴地读了起来,读完感觉酣畅淋漓。之前很多不清晰的点,逐渐清晰了起来,尤其是架构、性能分析和优化方法。
为了让更多人能够学习书中的内容,我们有了翻译这本书的念头,于是便跟Denis联络,申请翻译这本书,很快便得到了Denis的同意。然后,通过朋友联系到了机械工业出版社,洽谈协商后便开始了本书的翻译工作。因为本书主要讲的是芯片架构和编译优化,属于计算机领域基础软件部分,所以并不是全民追捧的技术热点,机械工业出版社对基础软件技术的专注和追求让人印象深刻。
本书系统地整理和总结了Denis在easyperf.net博客中所分享的内容。本书第一部分介绍性能评测方法、CPU微架构运行机制与内存层级管理、基于CPU的性能分析方法论(自顶向下的微架构分析方法和屋顶线性能模型等)及相关工具。第二部分介绍如何基于LLVM编译器对自顶向下微架构分析的不同瓶颈类型进行优化。相比传统的架构和编译原理相关书籍,本书更贴近实战,详细介绍Intel Skylake处理器的硬件架构和相关特性,而不是泛泛地讲一些概念。其中对于编译优化部分,本书没有纠结于繁杂的编译原理,而是直接介绍LLVM提供的编译优化方法及原理。所以,我们可以在阅读本书的过程中直接对自己的C/C++代码进行剖析和优化。在实际工作中,我们直接通过PGO编译和火焰图剖析对某个算法实现了10%的性能优化。略有遗憾的是,本书主要介绍的是Intel x86平台的内容,对ARM和RSIC V等平台特性没有深入介绍,同时后两个芯片平台的性能剖析硬件支持也远远落后于x86平台。不过,得益于LLVM的跨平台特性,本书中讲到的几乎所有优化方法都适用于其他平台。
在此也提醒一下读者,本书介绍的分析和优化方法主要用于解决代码在CPU微架构流水线上运行的效率问题。如果你要优化的程序本身在业务逻辑上就存在性能缺陷,那么本书介绍的方法可能对你帮助不大。在你解决了业务上的性能问题后,本书介绍的方法也许可以助你一臂之力,让你的代码被优化或者被编译得更适合目标CPU的微架构,从而提升应用程序的性能或者降低能耗。
本书的翻译不是我一个人的功劳,当我刚开始投入时,字节跳动的董一峰和世纪互联的崔永新已经开始了一些翻译工作。参与进来后,我就承担起了组织大家一起翻译本书的工作。后来在操作过程中,由于一峰和永新工作比较繁忙,相对参与得比较少。董一峰为本书做出了非常关键和基础的贡献,打造了从Markdown到PDF的构建环境,解决了本书翻译过程中的排版大难题,让我们能够更多地关注书中的内容而非排版。后来,腾讯云的李成栋通过朋友介绍参与了进来,完成了本书第3章、跋和附录A、附录B的翻译,以及大部分的校译工作。此外,编译优化方向的硕士研究生韦清福同学也参与了本书的校译工作,尤其对第8章中的循环优化和向量化等内容提供了大量的建设性意见。在此,一并衷心感谢所有参与翻译和校译工作的朋友们,是大家的一致努力让本书的翻译工作得以完成。尽管各位译者都尽可能想要把原文翻译准确,但难免有疏漏之处,欢迎大家斧正。
翻译本书占用了译者周末和凌晨的绝大部分时间,非常感谢家人的理解和成全,没有他们的全力支持,翻译工作是不可能完成的。
朱金鹏
于北京