多年前,在上一家公司参与某编译器项目时,为了度量编译器生成汇编指令的效率,我曾经尝试过基于控制流图(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章中的循环优化和向量化等内容提供了大量的建设性意见。在此,一并衷心感谢所有参与翻译和校译工作的朋友们,是大家的一致努力让本书的翻译工作得以完成。尽管各位译者都尽可能想要把原文翻译准确,但难免有疏漏之处,欢迎大家斧正。
翻译本书占用了译者周末和凌晨的绝大部分时间,非常感谢家人的理解和成全,没有他们的全力支持,翻译工作是不可能完成的。
朱金鹏
于北京
我写这本书的目的很简单:帮助软件开发人员更好地理解应用程序在现代硬件上的性能。我知道,对于初学者甚至资深的开发人员来说,该话题可能会让他们感到困惑,这种困惑主要发生在没有从事过与性能相关的工作的开发人员身上。不过这并不是问题,毕竟所有的专家都曾是初学者。
我至今还记得刚开始进行性能分析的那些日子:盯着不熟悉的指标,试图匹配一些不匹配的数据,每日都感到非常困惑。我花了好几年的时间才终于融会贯通,把相关的知识拼图拼凑到了一起。当时,唯一的信息来源是软件开发者手册,但是它不是主流开发者喜欢阅读的文档。所以,我决定写这本书,希望本书能够让开发人员更容易地学习性能分析的相关概念。
认为自己是性能分析初学者的开发者,可以从本书的开头逐章阅读。第2~4章为开发者提供了阅读后面各章所需的必备知识,已经熟悉这些概念的读者可以选择跳过这些章节。此外,本书可用作优化软件应用程序的参考指南。读者可把第7~11章的内容作为调优代码的灵感来源。
本书主要面向性能关键型应用程序和底层优化软件的开发者。这里只列举几个相关领域,如高性能计算(High-Performance Computing,HPC)、游戏开发、数据中心应用(如Facebook和Google等)、高频交易。但是,本书的应用范围并不局限于上述行业。对于任何希望更好地了解应用程序性能,希望知道如何诊断和改进应用程序的开发者来说,本书都是有用的。我希望本书中介绍的内容可以帮助读者培养可用于日常工作的新技能。
读者应当具备C/C++编程语言的基本知识,以方便理解本书的示例。如果读者具备基本的x86汇编语言阅读能力则更佳,但这并非严格要求。读者还需要熟悉计算机架构和操作系统的基本概念,如中央处理器、内存、进程、线程、虚拟内存和物理内存、上下文切换等。如果读者还不熟悉上述术语的话,建议先学习一下相关知识。