跳转至内容

软件工程/工具/性能分析简介

来自Wikibooks,开放世界中的开放书籍

在软件工程中,程序性能分析软件性能分析或简称性能分析,是一种动态程序分析(与静态代码分析相对),它通过收集程序执行期间的信息来调查程序的行为。这种分析的通常目的是确定程序的哪些部分需要优化——以提高其整体速度、减少其内存需求,或者有时两者兼而有之。

  • (代码)性能分析器是一种性能分析工具,最常见的是仅测量函数调用的频率和持续时间,但除了更全面的性能分析器之外,还有其他特定类型的性能分析器(例如内存性能分析器),能够收集广泛的性能数据。
  • 指令集模拟器——也必然是一个性能分析器——可以测量程序从调用到终止的全部行为。

收集程序事件

[编辑 | 编辑源代码]

性能分析器使用各种技术来收集数据,包括硬件中断、代码插桩、指令集模拟、操作系统钩子和性能计数器。性能分析器的使用在性能工程过程中被“调用”。

性能分析器的使用

[编辑 | 编辑源代码]

程序分析工具对于理解程序行为极其重要。计算机架构师需要这样的工具来评估程序在新架构上的性能。软件编写人员需要工具来分析他们的程序并识别代码的关键部分。编译器编写人员经常使用此类工具来了解他们的指令调度或分支预测算法的执行效果……(ATOM,PLDI,'94)

性能分析器的输出可能为:

  • 观察到的事件的统计摘要概要
摘要概要信息通常显示在事件发生位置的源代码语句上,因此测量数据的大小与程序的代码大小成线性关系。
 /* ------------ source------------------------- count */             
 0001             IF X = "A"                     0055
 0002                THEN DO                       
 0003                  ADD 1 to XCOUNT           0032
 0004                ELSE
 0005             IF X = "B"                     0055
  • 记录事件的流(跟踪
对于顺序程序,通常使用摘要概要就足够了,但并行程序中的性能问题(等待消息或同步问题)通常取决于事件的时间关系,因此需要完整的跟踪才能了解正在发生的事情。
(完整)跟踪的大小与程序的指令路径长度成线性关系,使其在某种程度上不切实际。因此,可以启动程序中的一个点,并在另一个点终止跟踪以限制输出。
  • 与虚拟机的持续交互(例如通过屏幕显示进行连续或周期性监控)
这提供了在执行期间任何所需点切换跟踪开/关的机会,以及查看有关(仍在执行的)程序的正在进行的指标。它还提供了在关键点暂停异步进程以更详细地检查与其他并行进程交互的机会。

性能分析工具从 20 世纪 70 年代初就在 IBM/360 和 IBM/370 平台上存在,通常基于定时器中断,这些中断在设定的定时器间隔记录程序状态字 (PSW) 以检测执行代码中的“热点”。这是早期采样(见下文)的例子。1974 年初,指令集模拟器允许进行完整的跟踪和其他性能监控功能。

Unix 上的性能分析器驱动的程序分析至少可以追溯到 1979 年,当时 Unix 系统包含一个基本工具“prof”,该工具列出每个函数及其使用的程序执行时间的多少。1982 年,gprof 将此概念扩展到完整的调用图分析[1]

1994 年,数字设备公司的 Amitabh Srivastava 和 Alan Eustace 发表了一篇论文,描述了 ATOM。[2] ATOM 是一个将程序转换为其自身性能分析器的平台。也就是说,在编译时,它将代码插入到要分析的程序中。插入的代码输出分析数据。这种修改程序以分析自身的技术被称为“插桩”。

2004 年,gprof 和 ATOM 论文都出现在有史以来 50 篇最有影响力的 PLDI 论文列表中。[3]

基于输出的性能分析器类型

[编辑 | 编辑源代码]

扁平性能分析器

[编辑 | 编辑源代码]

扁平性能分析器根据调用计算平均调用时间,并且不根据被调用方或上下文分解调用时间。

调用图性能分析器

[编辑 | 编辑源代码]

调用图性能分析器显示函数的调用时间和频率,以及基于被调用方的调用链。但是上下文不会被保留。

数据收集方法

[编辑 | 编辑源代码]

基于事件的性能分析器

[编辑 | 编辑源代码]

此处列出的编程语言具有基于事件的性能分析器

  • Java:JVMTI(JVM 工具接口)API(以前称为 JVMPI(JVM 性能分析接口))为性能分析器提供挂钩,用于捕获诸如调用、类加载、卸载、线程进入离开等事件。
  • .NET:可以将性能分析代理作为 COM 服务器附加到 CLR。与 Java 类似,运行时随后会向代理提供各种回调,用于捕获诸如方法 JIT/进入/离开、对象创建等事件。特别强大之处在于性能分析代理可以以任意方式重写目标应用程序的字节码。
  • Python:Python 性能分析包括 profile 模块、hotshot(基于调用图)以及使用 'sys.setprofile' 函数来捕获诸如 c_{call,return,exception}、python_{call,return,exception} 等事件。
  • Ruby:Ruby 也使用类似于 Python 的接口进行性能分析。存在 profile.rb 模块中的扁平性能分析器和 ruby-prof C 扩展。

统计性能分析器

[编辑 | 编辑源代码]

一些性能分析器通过采样来运行。采样性能分析器使用操作系统中断定期探测目标程序的程序计数器。采样概要通常在数值上不太准确和具体,但允许目标程序以接近全速运行。

得到的数据不是精确的,而是统计近似值。实际的误差通常大于一个采样周期。事实上,如果一个值是采样周期的n倍,则其预期误差为n个采样周期的平方根。 [4]

在实践中,采样分析器通常可以比其他方法提供目标程序执行的更准确的图像,因为它们对目标程序的侵入性较小,因此不会产生太多副作用(例如内存缓存或指令解码流水线上的副作用)。此外,由于它们对执行速度的影响较小,因此可以检测到其他情况下会被隐藏的问题。它们也相对不容易高估小型、频繁调用的例程或“紧凑”循环的成本。它们可以显示在用户模式下花费的时间与可中断内核模式下(例如系统调用处理)花费的时间的相对数量。

尽管如此,处理中断的内核代码会导致轻微的 CPU 周期损失,转移缓存使用,并且无法区分不可中断内核代码中发生的各种任务(微秒级活动)。

专用硬件可以超越这一点:一些最近的 MIPS 处理器 JTAG 接口有一个 PCSAMPLE 寄存器,它以真正无法检测的方式对程序计数器进行采样。

一些最常用的统计分析器包括 AMD CodeAnalyst、Apple Inc. Shark、gprof、Intel VTune 和 Parallel Amplifier(Intel Parallel Studio 的一部分)。

Instrumentation 分析器

[编辑 | 编辑源代码]

一些分析器使用附加指令检测目标程序以收集所需的信息。

检测程序可能会导致程序性能发生变化,从而可能导致结果不准确和海森堡错误。检测始终会对程序执行产生一定影响,通常会使其变慢。但是,检测可以非常具体,并且可以仔细控制以使其影响最小。对特定程序的影响取决于检测点的放置和用于捕获跟踪的机制。硬件对跟踪捕获的支持意味着在某些目标上,检测可以在单个机器指令上进行。检测的影响通常可以从结果中推导出(即通过减法消除)。

gprof 是一个使用检测和采样的分析器示例。检测用于收集调用者信息,而实际的时间值是通过统计采样获得的。

  • 手动:由程序员执行,例如通过添加指令来显式计算运行时间,简单地计数事件或调用测量 API(例如应用程序响应测量标准)。
  • 自动源代码级别:根据检测策略,由自动工具向源代码添加检测。
  • 编译器辅助:例如:gprof 的“gcc -pg …”、Quantify 的“quantify g++ …”
  • 二进制翻译:工具向已编译的二进制文件中添加检测。例如:ATOM
  • 运行时检测:在执行之前,代码会被检测。程序运行完全由工具监督和控制。例如:Pin、Valgrind
  • 运行时注入:比运行时检测更轻量级。在运行时修改代码以跳转到辅助函数。例如:DynInst

解释器检测

[编辑 | 编辑源代码]
  • 解释器调试选项可以在解释器遇到每个目标语句时启用性能指标的收集。字节码、控制表或 JIT 解释器是三个示例,它们通常对目标代码的执行具有完全控制权,从而能够提供极其全面的数据收集机会。

虚拟机/模拟器

[编辑 | 编辑源代码]
  • 虚拟机:通过在虚拟机下运行(通常)未修改的程序来收集数据。例如:SIMMON
  • 模拟器虚拟机:通过在指令集模拟器下运行未修改的程序以交互方式和选择性地收集数据。例如:SIMON(批处理交互式测试/调试)和 IBM OLIVER(CICS 交互式测试/调试)。

参考文献

[编辑 | 编辑源代码]
  • Dunlavey,“Performance tuning with instruction-level cost derived from call-stack sampling”,ACM SIGPLAN Notices 42, 8(2007 年 8 月),第 4-8 页。
  • Dunlavey,“Performance Tuning: Slugging It Out!”,Dr. Dobb's Journal,第 18 卷,第 12 期,1993 年 11 月,第 18-26 页。
[编辑 | 编辑源代码]
华夏公益教科书