第二章 性能测量&分析概述(Performance Measurements & Analysis in a Nutshell)
在上一章中,我们研究了为什么性能很重要,甚至诊断了一个简单的性能问题。在本章中,我们将总览执行性能分析的其他方法。为了证明这些问题,我们将诊断与练习1.1中调查的相同问题。我们还将对比这些不同的方式,并回顾它们的利弊。然而,在冒险通过这些替代方案之前,让我们首先更好地了解衡量时间的实际含义。
测量时间(Measuring time)
测量时间是所有与性能相关的工作的核心。性能分析旨在优化两个关键维度的系统运行:
- 执行场景所需的时间
- 系统执行这些情景的能力,也称为容量
当然,第一项要求我们能够测量时间间隔。正如我们将看到的,第二项也需要时间测量。在当代计算机系统上,有许多不同的方法可以测量时间,从基于秒表的粗制滥造测量,到基于高精度高频性能计数器的测量。
测量场景持续时间的最简单、最天真的方法之一是使用常规秒表(stopwatch)。正如您可以想象的那样,这种方法缺乏准确性,而且非常劳动密集型——例如,尝试用秒表测量计算机启动几十次所需的时间(以获得统计准确性),您很快就会意识到这种方法不具备扩展性。此外,秒表不足以测量需要毫秒级精度的场景。即使是我们中最优秀的人,在使用秒表时,通常也不能精确地记准时间。幸运的是,有更好的方法来衡量和报告场景持续时间。
大多数刚接触性能工程的人都是从使用秒表般的方法测量场景的持续时间(例如用户交互的响应性)开始的。当然,这只适用于要花相当长时间的场景,这种场景一般都会给用户展示进度条。显然,对于足够快的场景(例如响应式用户交互),依赖人类感知的测量方法根本不起作用。特别是,手动秒表测量中涉及的误差通常与您想要测量的活动具有相同的数量级。不过,秒表测量是你经常使用的东西,因为它的简单性和缺乏更好的工具。秒表的精度在用于验证较长运行场景的问题时有时仍然可以接受,。
即使在秒表接近精度可能足够的场景中(即测量延长场景时),您仍然需要确保统计的健全性。您可以通过多次测量场景延迟,然后计算中位数和百分位数来实现此目的。解决此问题的一种常见方法是编写测量的工作流脚本,并在脚本中的正确点包括时间戳探测器。在Windows的脚本环境中,您可以在CMD控制台执行%time%
或者在PowerShell控制台执行Get-Date
命令来获取时间差。当使用重复测量持续比较长时间的场景时,这种时间测量可以为该场景的持续时间提供足够好的时间统计。%time%
和Get-Date
后面的时间源称为系统时间源,其精度范围为1-15.625ms(后者是默认值),这依赖于时间源是怎么配置的。
虽然从技术上讲,系统时间精度应该足够好,可以测量需要300-500毫秒的场景,但由于实际运行这些系统命令的成本和解释命令提示符环境的开销,从脚本中这样做是不实际的。要测量<300~500ms精度的场景,您需要在代码中加时间统计代码,而不再能通过脚本来测量。(即在代码中的兴趣点添加时间戳标记)。系统时间可以在代码中使用,但正如我们稍后将向您展示的那样,对于许多感兴趣的场景,您确实希望通过使用所谓的高精度时间源获得更精确的时间。
注意:正如我们稍后将更正式地看到的那样,300-500ms处于系统可视响应用户输入的可接受响应时间的上限。有些人把这叫做足够快,而另一些人则说这差点没响应。由于这本书的重点是确保用户体验非常快速和快速(当然,在用户的脑海中瞬间将是理想的目标),我们显然需要一种方法来精确测量短于300ms的时间间隔。
计算机系统中有很多东西可以跟踪时间。根据系统架构,您可能会遇到ACPI计时器、PM计时器、CMOS计时器、HPET计时器等时间源。这些时间源统称为硬件计时器。处理器本身还提供TSC(时间戳计数器)时间测量工具,可通过读取时间戳计数器(RDTSC)指令访问该工具。在测量时间时,您通常不会直接接触到这些时间源。然而,操作系统确实利用它们来实现各种时间测量API,用于系统时间和高精度时间测量。
注意:在.NET中,测量时间的常见方法是使用System.Dias.StopWatch类。请注意,此类不保证高精度测量——此类支持是系统特定的。要检查StopWatch类是否确实为您提供了高精度时间测量,您可以使用以下C#代码:
System.Diagnostics.StopWatch( (IsHighResolution==TRUE) ? QPC : SystemTime)
将测量场景的持续时间映射到测量它们所需的测量精度,并枚举典型运行环境的相应Windows API和命令,得到下面的图示
正如你所看到的,秒表测量只涵盖了非常小的场景范围。人眼显然对它可以记录的场景持续时间有一个下限。同时它可以跟踪的场景的持续时间也有上限。超出这一时间范围的情景(即非常快的情景<2s或相对缓慢的情景>5min)不适合取决于人类反应的测量。
为了解决人类对反应时间和注意力范围的限制,我们可以依靠自动化。通过脚本获取的时间测量足够好,可以测量超过一秒钟的时间跨度。精度如果要求更低的话,则从脚本中调用时间测量命令的时间就会开始影响您的测量。为了更精确,您需要在代码中添加计时代码。查看图2.1,您可以看到,通过众多列出的API提供的系统时间可以让您精确到数百毫秒,或者比脚本好一个数量级。如果您想获得更精确的信息,您需要使用利用高精度时间源的API,通常称为QPC(QueryPerformanceCounter Win32 API的缩写)。
注意:从历史上看,当CPU以MHz频率运行时,系统时间的精度“足够好”。随着时钟速度快得多的CPU的引入,系统时间精度不足以测量更高精度的微活动。虽然您仍然可以使用系统时间来测量一些边缘响应场景(即测量300-500ms的持续时间),但是如果仅依赖系统时间精度,再想将此类场景的持续时间分解为更细节的基础子活动就面临困难。因此,您将看到我们在本书中大量利用了更精确的QPC时间源。
你说,为什么系统时间和QPC都要测量时间?系统时间表示每个人都习惯的日历时间。这使得日志中的发生时间能够映射到日常人类活动。另一方面,QPC从系统通电开始计数,并且与日历时间没有相关性(尽管您可以使用上次引导系统时间来映射QPC时间到日历时间)。因此,两者都有他们的用途。系统时间为您提供日历时间上下文,而QPC时间提供更高精度的测量。
注意:在Windows 8中,通过引入WDK KeQuerySystemTimePrecise()
和Win32 APIGetSystemTimePreciseAsFileTime()
,系统时间的API精度得到了提高,更多详细信息,请参阅MSDN。
个人补充:初步看了下MSDN, Win32 API GetSystemTimePreciseAsFileTime
最大的作用是用于高精度测量,且需要关联系统时间的场景。
众所周知,业内许多成熟的代码库在其自定义测量中仍然依赖于系统时间。正如我们稍后将看到的,那些选择使用ETW的实现可以在这些时间源之间轻松切换,而无需任何代码更改。
现在我们已经讨论了如何测量时间,接下来让我们看看Windows附带的许多性能监控工具,看看如何使用它们来解决我们在第1章中讨论过的问题。
使用Windows内置工具识别CPU饱和问题(Identifying CPU saturation using Windows inbox performance tools)
回忆一下我们在第1章练习1.1中回顾过的性能问题的基本示例。在该练习中,我们能够定位导致系统运行缓慢的原因是CpuHoger.exe导致了CPU饱和。为了收集证据,我们使用WPR捕获ETL跟踪,然后依靠WPA来确定罪魁祸首进程。
对于由单个进程导致的如此简单的CPU饱和的场景,实际上还有其他内置工具(它们与Windows捆绑在一起)可以定位该场景。让我们利用这个机会回顾一下其中的一些。如果您熟悉这些工具及其局限性,请随时跳过这些练习
任务管理器(Task Manager)
任务管理器随Windows一起提供,是最常用的面向最终用户的工具,旨在识别和帮助缓解典型的饱和来源(例如,通过终止故障进程或降低其执行优先级缓解系统卡慢)。任务管理器从XP到Windows 7基本上没有变化,在Windows 8中经历了相当大的演变。特别是,“性能”选项卡已完全重新设计,以近乎实时地显示关键系统性能指标(KPI)(即资源使用情况可以每秒钟更新一次)。这些指标包括CPU、内存、存储和网络。
练习2.1 使用任务管理器识别CPU饱和问题
概述
在本练习中,我们将使用Windows 8版本的任务管理器。让我们看看当我们运行CpuHogger.exe时,任务管理器会显示什么。
分析方法
本节介绍如何使用任务管理器定位导致系统卡慢的进程。
-
打开任务管理器
-
切换到详细信息界面
-
切换到性能标签页
-
运行
CpuHogger.exe
-
我们可以观察到系统变得未响应,当重新可以响应是你将看到一个类似下图的凸起。
-
请注意,在CpuHoger.exe运行时,您无法与任务管理器交互。一旦CpuHoger.exe停止运行,任务管理器再次变得响应,我们看到CPU实际上在其无响应的时间间隔内饱和。不幸的是,任务管理器是一个实时监测工具,没办法回到过去检查是哪个具体进程导致的。你必须在出问题的过程中找到罪魁祸首。
-
CpuHoger碰巧使用应用程序可用的最高执行优先级,而任务管理器以默认优先级运行,因此出现问题时它也没有响应。我们将在第9章更多地讨论执行优先级。目前,请记住,优先级较高的进程比优先级较低的进程获得更多的CPU时间。
-
通过将任务管理器切换为以实时优先级运行,我们可以使它以比CpuHoger更高的优先级运行。这将使我们能够使用其GUI识别罪魁祸首进程。要将任务管理器切换为实时优先级运行,请右键单击“详细信息”选项卡中的条目,选择“设置优先级”,然后选择“实时”,如图2.3所示。
-
现在,我们已经确保了任务管理器以实时优先级运行,让我们来看看谁消耗了最多的CPU时间。为此,请通过单击“详细信息”选项卡中的“CPU”列的标题,按降序排序
-
现在,让我们添加基本优先级列,以查看哪个进程以什么优先级执行。为此,右键单击标题,选择选择列,然后选择基本优先级,如图2.4所示。
-
再次运行CpuHogger.exe
-
您应该看到类似于图2.5中所示的内容。也就是说,当CpuHoger.exe运行时,它被列在详细信息列表的顶部,占用99%的CPU时间。请注意,Taskmgr.exe以实时优先级运行,而CpuHoger.exe以正常优先级运行。这确保了我们能够与任务管理器交互,即使CpuHoger使CPU饱和。
注意:为了确保CPU饱和,CpuHoger将其工作线程的优先级提高到最高可用的非实时优先级——即优先级15。当我们将任务管理器设置为以实时优先级运行时,它的线程以24到26的优先级运行,这要高得多,使它能够保持响应。线程执行优先级不是您可以在任务管理器中看到的。在第9章中,我们将向您展示如何在WPA中查看此信息。
-
您还可以通过单击进程选项卡观察CpuHoger.exe的高CPU使用率。图2.6显示了一个与您将在那里看到的类似的视图。请注意,在查看CPU以外的资源饱和时,“进程”选项卡可能很有用。
小结
在本示例中,我们已经向您介绍了如何使用任务管理器识别导致CPU饱和的罪魁祸首进程。为了确定实际进程,我们必须将任务管理器提升到实时优先级,并在问题发生时捕获问题。任务管理器不提供记录工具和离线分析功能,使其有用性仅限于帮助识别持续的CPU饱和问题.
正如我们刚才看到的,任务管理器基本上提供了反映系统活动的实时视图
注意:任务管理器默认使用的1秒1次的正常更新速率,在高更新速率下以0.5秒更新一次,在低更新速率下以4秒更新一次,您可以查看从30秒(高更新频率)到4分钟(低更新频率)的总CPU使用率的整体趋势图。
当然,这里的关键限制是,要查看哪些进程导致了高CPU使用率,我们需要监控问题发生时正在更新的列表,这并不总是实用的。为了更好地查看当时发生的事情,我们可以使用另一个内置工具,称为资源监视器。在下面的练习中,我们将使用该工具对同一问题进行分析。
资源监视器(Resource Monitor)
虽然任务管理器提供了对系统性能的基本描述,但对一个展现关键系统资源的活动细节的视图通常是问题诊断所必需的。为了满足这一需求,资源监视器已添加到Windows Vista中的操作系统中。虽然此工具从一个版本到另一个版本一直在发展,但其关键功能集在Windows 8中基本上保持不变。
练习2.1 使用资源监视器识别CPU饱和问题
分析方法
-
通过任务管理器“性能”选项卡页下面的按钮打开资源监视器,或者命令行执行
perfmon.exe /res
打开 -
与任务管理器不同,资源监视器保持跟踪完整1分钟的CPU活动,因此即使您无法实时观察问题,您仍可以在一分钟时间窗口内看到问题。
-
可选:与上一个练习一样,您可以使用任务管理器提高资源监视器的优先级。为此,请在任务管理器的“详细信息”选项卡中显示的进程列表中找到PerfMon.exe,并将其CPU优先级设置为实时(有关如何执行此操作的示例,请参阅图2.3)。请注意,查看CPU使用历史记录和识别罪魁祸首进程不需要这样做,但只有当我们提高资源监视器的优先级时,才能在CpuHoger.exe运行时实时观察CPU使用峰值。
-
运行CpuHogger.exe
-
请注意,系统变得无响应。如果您提高了资源监视器的优先级,您会注意到它将继续更新自己,因为它的运行优先级高于CpuHogger.exe。如果您没有,它将显示挂起,就像任务管理器一样,直到CpuHoger.exe完成,但随后将刷新并显示CPU使用情况。
-
在CpuHogger.exe退出后,你应该可以看到类似图2.7显示的情况:
-
正如您所看到的,CpuHoger位于列表的顶部,在其生命周期内平均占总CPU利用率的55%,如“平均CPU”列中所示。这是迄今为止列表中最高的CPU使用者。
注意: 从资源管理器中看到CPU一列的CpuHoger.exe的CPU使用率为23%,它表示从上次采集到此次期间的CPU使用率。默认情况下,资源监视器使用1s采样频率。
-
资源监视器还附带了用于关键系统资源的专用选项卡,包括CPU。在CPU选项卡中观察CpuHogger.exe时,您将看到与2.8所示类似的内容
-
请注意,在CPU选项卡中,除了CPU总体使用情况外,您还可以查看系统上每个逻辑核的CPU历史记录。由于CpuHoger.exe使所有可用的逻辑处理器饱和,因此我们可以看到系统上所有逻辑处理器的CPU利用率相似。
注意:通过观察每个CPU核利用率视图, 可以更容易看到为什么CpuHogger.exe的平均使用率大概为53%。(这里感觉看总体的话,在1分钟的周期内,肯定没有占到53%。 那是不是意味着,联系到上面的采集周期是1s1次,因此猜测比如这个程序运行15s,那么在这15s的采样周期内,CpuHogger.exe大概会占53%多的CPU时间片,应该数据是由此而来。)
小结
在本示例中,您已经学习了如何使用资源监视器识别导致CPU饱和的罪魁祸首进程。与任务管理器不同,不需要将资源监视器提升到实时优先级,因为它可以记录过去60s的历史记录。不过,与任务管理器类似,资源管理器也不提供记录工具和离线分析功能,它局限于帮忙分析在程序执行的最近1分钟内的CPU饱和问题。
正如我们刚才看到的,资源监视器提供了一个基本的一分钟跟踪视图,以了解系统活动。您可以使用另一个名为Performance Monitor的内置工具进一步进行此分析。在以下练习中,我们将使用性能监视器分析同一问题。
性能监视器(Performance Monitor)
虽然任务管理器和资源监视器提供了对系统性能的基本观察见解,但在分析已经发生的事情时,您通常不想仓促行事。事实上,在许多情况下,你甚至不在那里实时看到它。当然,有时您也没有对有关计算机的物理(甚至远程)访问权限。显然,离线性能分析的需要可能至关重要。要实现离线性能分析,我们需要能够以性能跟踪(例如日志)的形式收集证据。
实际上,当我们捕获ETL文件时,我们已经在练习1.1中成功地收集了一个这样的Trace。此性能跟踪日志帮助我们诊断CpuHoger.exe的CPU饱和问题。正如我们之前提到的,Windows附带了两个互补的检测平台,形式是Windows性能计数器(PCW)和Windows事件跟踪(ETW)。当我们在第1章的练习1.1中捕获ETL跟踪时,我们使用ETW平台进行性能测量。现在,我们来回顾一下如何利用PCW来诊断该问题。
早在Windows 95, Windows就与一个专门用于性能监控的工具捆绑在一起。该工具最初称为系统监视器(SysMon.exe),在Windows 2000中被重新命名为性能监视器(PerfMon.exe)。它构建在PCW之上,允许您跟踪特定性能计数器(如CPU和磁盘利用率)随时间推移的值。在过去几十年里,多个应用程序、服务和驱动程序也提供了自己的性能计数器。PerfMon现在通常用于在大时间跨度内监控系统的性能。
接近实时监控的性能监视器
默认情况下,性能监视器近乎实时地跟踪当前活动。具体来说,您可以看到您选择监控的PCW计数器的最近100秒的数据。这与我们在任务管理器和资源监视器中看到的视图相似。在下面的练习中,让我们尝试将此监控功能用作CPU饱和诊断工具。
练习2.3 通过性能监视器的当前活动视图监控CPU饱和问题
分析方法
本节介绍用于使用Performance Monitor的当前活动视图确定导致系统上出现卡慢的罪魁祸首进程的分析工作流程。
-
开始菜单打开性能监视器
-
打开性能监视器图表工具,如图2.9所示
-
请注意,此视图显示了随时间推移的总处理器利用率。在近乎实时的观察模式下运行时,PerfMon会显示选定性能计数器的100秒后的值。默认情况下,已选择
%Processor Time
,会默认展示CPU时间趋势注意:与任务管理器和资源监视器不同,它们在显示图形信息时利用视图平移,性能监视器在显示新数据时循环覆盖以前的数据
-
现在,让我们通过运行CpuHoger.exe来重现性能问题。在应用程序完成其邪恶行为后,您将看到一个类似于图2.10所示的视图。
-
我们现在知道CPU已经饱和,但我们还不知道是哪个进程造成的。要找出答案,让我们尝试使用“每个-进程“性能计数器。
-
点击添加按钮或者快捷键
Ctrl+Shift+N
,打开类似2.11所示界面: -
此视图显示系统上所有可用的性能计数器,按性能计数器组分组。要开始显示实际计数器随时间推移的值,您需要将该计数器的实例添加到右侧列表框中。
-
找到
Process
选项卡,只选择% Processor Time
观察进程的CPU时间,然后在下面的框中选择所有进程,然后添加。 -
略,包含在8步里了
-
由于实例是按字母顺序列出的,CpuHoger应出现在conhost#2和csisyn~1之间。但是,正如您可能注意到的,CpuHoger.exe没有列出在那里,如图2.12所示。这并不奇怪,因为我们还没有启动它。、
-
添加所有实例。
-
单击确定,然后运行CpuHoger.exe。您最终看到的内容将与图2.14中所示的视图相似。请注意,我们可以选择加号右边的右边的画笔按钮突出显示选定的数据行,重点关注处理器的总使用情况。
-
请注意,总处理器使用率如预期的那样上升,但没有特定进程的CPU使用率随之上升。事实上,您可以看到,在7:12:38PM和7:12:58PM期间,其他进程的CPU使用率降低了。只有当总CPU使用率从100%开始下降时,我们才会看到其中一些进程以持续到晚上7:13:05的突发形式恢复其CPU使用率模式。
注意:正如我们稍后将了解的那样,这被称为CPU匮乏,CpuHoger.exe阻止了所有其他活动取得应有的进展。
- 显然,如果没有一些进程实际耗尽CPU,总CPU使用率不太可能在大约20秒内跃升到100%。我们知道这是哪个进程,因为我们自己启动了它,但查看捕获的进程列表,您不会在其中找到CpuHoger.exe。这是PerfMon的一个已知限制,它在监视<所有实例>处理器计数器时不跟踪新启动的(即临时)进程。
注意:此限制仅存在于PerfMon的实时监控功能。正如我们稍后将看到的,它不会影响PCW跟踪到BLG文件。
小结
在本示例中,我们试图使用性能监视器识别导致CPU饱和的罪魁祸首进程,但再次遇到了工具的限制。具体来说,我们不能使用性能监视器的实时观察视图,因为它无法监视在监视开始后才运行的进程。
性能监视器已经存在了近20年(截至本书撰写时),性能计数器生态系统非常活跃。虽然自Windows 2000以来,PerfMon的UI没有进行重大投资,但该工具仍在许多服务器监控场景中广泛使用。如果您想了解更多关于PerfMon的信息,您只需要在线搜索。
性能监视器离线BLG日志分析(Performance Monitor offline BLG trace analysis)
在上一个练习中,我们尝试通过PerfMon的实时监控功能使用PCW诊断CpuHoger.exe导致的CPU饱和。不幸的是,我们没有成功,因为PerfMon的当前活动视图不跟踪新启动的进程。但是,有一种可以利用PCW平台的方法来诊断此问题,即使用PerfMon的离线分析功能,以BLG(Binary Log :二进制日志)跟踪的形式。
练习2.4 通过性能监视器的离线BLG日志分析CPU饱和问题
日志采集方法
本节介绍了收集数据所需的数据收集工作流,然后我们将使用这些数据来确定导致您在系统上经历的卡慢的原因。
-
启动性能监视器
-
展开左侧的数据收集器集(Data Collector Set)项目,然后右键单击用户定义(User Defined)项目,然后单击新建|数据收集器集选项,如图2.15所示。
-
让我们将此数据收集器集称为“CPU使用率”,选择手动创建(高级),如图2.16所示,然后单击下一步
-
下一步选择性能计数器, 继续点击下一步, 如图2.17
-
在下一页上,单击添加...添加以下三个计数器,添加的过程和上一个练习中描述的过程类似:
\Process(*)\% Processor Time
\Processor(_Total)\% Processor Time
\Processor Information(_Total)\% Processor Utility
-
完成后,将采样间隔设置为一秒。完成后,您应该看到一个类似于图2.18所示的视图。
-
后面只需单击“完成”作为下一步。然后,您应该看到在用户定义文件夹下创建的CPU使用量数据收集器集,如图2.19所示。请注意,在左侧的“报告”节点下还创建了用户定义的\CPU使用情况报告文件夹。一旦我们收集了测量报告,我们就会在这里找到报告。
-
右键单击CPU占用率,然后选择Start,启动新创建的数据收集器集,如图2.20所示。
-
在收集的过程中,运行
CpuHogger.exe
-
请注意,系统再次变得无响应,但这应该不再是一个问题,因为我们现在正在后台记录系统活动。
注意:正如您将看到的,由于CpuHogger.exe的自大狂性质,它可能从PerfMon的数据收集中窃取CPU时间片,因此您可能仍然会丢失一些数据,
- 在
CpuHogger.exe
退出后,再次右键CPU使用率数据收集器并点击停止
分析方法
-
展开报告\用户定义下的CPU使用率文件夹以查找新生成的报告。虽然您的视图将有所不同,但您仍然可能在测量中看到间隙,总体使用率类似于图2.21所示。
-
现在,让我们添加每个进程%Processor Time计数器的All instances,以尝试查找违规进程。您会注意到,添加它们虽然仍然存在部分时间段无法看到数据的问题,如图2.22所示,但您可以看到CpuHoger.exe确实列在这些进程中,并且它在成功获取数据的时间范围内消耗了100%的CPU,如预期的那样(在100的顶部的一条小横线,图上不太好看)。
-
造成这些差距的原因是PCW是一个轮询基础架构,其中轮询代码在用户模式下运行(应我们的请求启动以收集测量数据)。此执行以正常优先级进行。由于CpuHoger.exe以更高的优先级运行,它可以阻止PerfMon的数据收集取得进展。前面我们尝试使用任务管理器和资源监视器时,我们已经遇到了这个问题。
-
不幸的是,在这种情况下,提高PerfMon UI应用程序(托管在mmc.exe中)的优先级并不能解决问题。实际上,计数器轮询发生在不同的进程(rundll32.exe)中,该进程为每个数据收集器集运行单独启动。
-
要使用“手动优先级提升”方法消除测量中的差距,我们必须先开始数据收集,在任务管理器中找到用于数据收集的rundll32.exe的特定实例,然后将其优先级提升到实时。然而,有多个rundll32.exe实例的情况并不罕见。找到对的进程可能是一个挑战,而且在实践中我们并不建议这样做。
-
如果我们真的这样做了,Gap就会消失,如图2.23所示。虽然您可以尝试确认这一点,但我们实际上不建议将“手动优先级提升”作为性能衡量方法。特别是,通过将进程提升到高优先级,您可能会影响你试图测量的场景。我们这么尝试只是为了更好地理解基于PCW的数据收集的局限性
注意:PCW从用户模式进程中采样,因此很容易受到CpuHoger等自大狂进程的影响。与PCW不同,ETW从系统自身内部收集数据,不受此类问题的影响。在下一节中,我们将更仔细地了解切换到ETW进行性能测量的好处。
小结
在本示例中,我们再次尝试使用性能监视器识别导致CPU饱和的罪魁祸首进程。我们没有使用其实时界面,而是依赖其对使用用户定义的Data收集器集捕获的BLG文件的离线分析,这使我们能够跟踪新启动的进程(包括CpuHoger.exe)的性能计数器。请记住,通过近乎实时的监控,我们无法跟踪新启动的进程
不幸的是,我们再次遇到了以正常优先级收集数据的限制,即它被CpuHogger.exe这种更高优先级的问题进程抢占了时间片。这导致了在我们需要的时候,我们的测量出现了偏差。然而,我们仍然可以瞥见CpuHoger.exe贡献的高CPU使用率。 并且通过提高基础收集进程的优先级(我们不建议您实际中这样做)来确认这一点。
数据收集器集可以成为性能监控的强大盟友。它允许您定义特定的PCW测量,并按需或特定时间表收集它们(您可以在文档或在线中阅读这一功能)。事实上,数据收集器集甚至允许您收集ETW测量值,或PCW和ETW的组合。请注意,生成的ETL跟踪在性能分析中不如WPR捕获的跟踪有用,因为它们缺少了许多关键的元数据。因此,在本书中,我们将重点讨论使用WPR捕获的跟踪。
注意:数据收集器集也可以使用LogMan.exe内置程序从命令行管理,以及使用Performance Logs And Alerts:性能日志和告警(PLA)通过Win32 API以编程方式管理。
注意:收集BLG文件的另一种快速方法是使用内置TypePerf程序。例如,要捕获每个进程CPU使用率,我们可以使用以下命令:typeperf "\Process(*)\% Processor Time" -f BIN -o PerProcessCpuUsage.blg
。好消息是,使用TypePerf,您可以知道应该提升哪个进程的优先级(即typeperf.exe进程本身)。
Performance Monitor还附带了报告生成功能,如果您在创建新的用户定义的数据收集器集时使用默认建议模板,您就可以获得这些功能。或者,您也可以只使用性能监视器附带的系统\系统性能数据收集器集。
注意:内置数据收集器集配置为仅捕获60秒的测量
虽然这些功能在稳态负载下对服务器系统进行容量测量非常有用,但这些报告通常不包含对性能问题执行有效根本原因分析所需的数据。
使用正确的工具进行工作
正如我们在上一节中所看到的,我们尝试过的用于诊断CPU饱和的每一个工具都有其缺点,任务管理器要求我们实时捕获问题。资源监视器确实给了我们一分钟的窗口,这要归功于它的尾随平均值,但没有提供离线分析功能。接下来,我们查看了性能监视器,如果使用正确,它允许我们使用BLG文件进行离线分析,这些文件确实指向消耗系统上大部分CPU的进程。正如我们所看到的,对于某些类型的性能问题,PCW可以成为根本原因分析的有效工具。话虽如此,它的有效性受到各种限制,我们稍后会继续讨论。
注意:我们所回顾的内容提供了一个相当完整的内置工具清单,以及大多数Windows套件中包含的推荐工具。与大多数工具生态系统一样,您还可以使用其他性能工具。其中一组值得明确调用的工具是SysInternal工具。在这个工具包中,您可以找到一个非常强大的工具,称为Process Explorer,提供了任务管理器和资源监视器提供的大部分功能,而且还有许多改进。有关更多详细信息,请访问http://www.sysinternals.com
回到第1章,在练习1.1中,我们已经看到了如何在WPR和WPA的帮助下使用ETW技术诊断相同的问题。PCW和ETW两种不同的技术,都支持使用性能跟踪(BLG for PCW,ETL for ETW)的离线分析,我们应该什么时候使用哪种技术?让我们在下一节中探讨这些测量和分析平台的利弊
PCW vs. ETW
回顾第1章,Windows中有两个可用于收集性能测量的替代平台:Windows性能计数器(PCW)和Windows事件跟踪(ETW)。
性能计数器使您能够采样反映系统当前状态的各种数据点。通过定期查询这样的计数器,您可以获得系统状态随时间变化的视图。例如,运行进程数的计数器将反映查询计数器时正在运行的进程数。如果您每隔一秒钟查询此计数器,您可以绘制一个趋势线图,以显示系统上运行的进程数随时间的变化趋势。
与性能计数器不同,性能计数器只能包含定期采样的数字数据,ETW事件由事件提供程序(Event Providers)(负责记录ETW事件的逻辑实体)在特定操作或状态转换发生时的确切时刻进行记录,并且包含丰富的数据。支持广泛的数据类型,包括字符串、结构化数据集、时间戳、GUID等。也与只能采样的计数器不同,ETW跟踪事件可以在状态更改发生时进行记录(即它们遵循推送模型(push model))。回到我们之前的监控系统上运行进程数量的示例,使用ETW的话,每次创建或终止进程时,您都会收到事件。从这些数据中,人们不仅可以获得在任何给定时间点在系统上运行的进程数量,而且还可以访问更丰富的信息,包括进程名称、确切的创建和终止时间戳、相应的命令行等等。
上面列出的两种机制是在Windows上收集性能信息的标准方法。它们都附带了对应的一组丰富的日志记录和处理的API,以及一组匹配的命令行和基于UI的工具,用于收集和分析数据。
PCW早在ETW之前就出现了(早在Windows 95之前)。它的主要目的是支持从Windows中的系统组件按需收集性能指标。为了处理大量数据,在内存稀缺、磁盘速度慢的时代,每次感兴趣的指标在更改其值时记录事件是不可行的。因此,这些度量将由其自己的组件聚合,通常以自定义的方式聚合。这为那个时代创造了一个足够好的监控平台,且该平台至今仍在使用——这主要是由于生态系统中众多产品对性能计数器的大量投资。
ETW是在Windows性能团队中Windows 2000创建的,但直到在Windows Vista发布后,针对了解和优化windows性能才有了很大的推动力,此时ETW才全面发挥了作用。它提供了对系统活动的更深入的视图,包括单个操作的级别,以及启动这些操作的代码。
从Windows 7开始,许多系统组件开始切换到ETW进行根因分析。在许多情况下,这提供了一定程度的维测功能,而以前,如果不首先重现问题,肯定无法定位到根因。让我们通过检查这两个平台之间的主要差异来回顾是什么让他们实现了飞跃。
下表展示了代码开发方面的对比。
领域 | PCW | ETW |
---|---|---|
添加检测 | 简单(对于支持实时聚合的数据) 中等(对于不支持实时聚合的数据) |
简单(仅日志事件) |
语言支持 | 广泛的(c/c++, .NET) | 广泛的(c/c++, .NET, JScript) |
下表展示了根因分析对比
类别 | PCW | ETW |
---|---|---|
活动 | 聚合的(累计值不断记录日志) | 离散的(支持深入分析) |
根因分析 | 一定程度受限 | 支持分析到代码 |
关于数据收集
类别 | PCW | ETW |
---|---|---|
主要预期功能 | 监控 | 调试 |
时间尺度 | 秒级~天级 | 毫秒级~分钟级(服务于性能分析) |
从发生到记录的时间戳的延迟 | 显著的(受限于计数器实现精度、计数器获取数据的损耗) | 非常接近实际发生时间(毫秒级) |
日志格式 | BLG | ETL |
执行优先级 | 用户态程序(可被高优先级活动抢占) | 系统优先级(不会被抢占) |
DBMS集成 | 支持 | 不支持 |
内容 | 有限的(数字) | 广泛的(数字、字符串、结构、数组、码流) |
开始采集后发生的瞬态活动能否监控到 | 支持(PerfMon不支持) | 支持 |
函数调用栈 | 不支持 | 支持 |
文件名 | 不支持 | 支持 |
活动跟踪 | 不支持 | 支持 |
跟踪便携性 | 简单 | 简单(通过WPR和xperf) |
远程收集 | 简单 | 困难 |
计量清单 | 简单(在PerfMon中通过列举“Providers”和指定的性能计数器) | 中等(能列举providers,但不是具体事件) |
工具 | GUI(PerfMon数据收集器)、CMD(LogMan、TypePerf) | GUI(WPRUI)、CMD(WPR、Xperf、TraceLog、LogMan) |
关于性能分析
类别 | PCW | ETW |
---|---|---|
离线分析 | 支持 | 支持 |
接近实时监控 | 支持 | 不支持(理论上可行,但是没有工具) |
非聚合数据分析 | 不支持(只有累计值) | 支持(单个事件) |
分析时间的聚合 | 困难(通过计数器暴露,通常无法导出) | 简单(只要工具支持就OK) |
程序化测量模式发现 | PDH Win32 API | TDH Win32 API |
关于工具
PCW | GUI | CMD | ETW | GUI | CMD |
---|---|---|---|---|---|
离线 | PerfMon | TraceRpt,TypePerf | 离线 | WPA | xperf,TraceRpt,WpaExporter |
在线 | 任务管理器,性能监视器,资源监视器 | TracerRpt | 在线 | 资源监视器(其中某些指标) |
表2.1至表2.4中列出的ETW的优势包括能够专注于亚秒级活动,以高精度将它们放置在时间轴上,以及能够获取调用堆栈和捕获非数字数据类型。这些优势使ETW成为典型性能问题根因分析的首选。
另一个值得记住的好处是,ETW基于事件的推送模型提供了更灵活的日志记录方法。您可以始终改进脱机分析功能,但一旦提供了性能计数器,那就是你在该版本中获得的所有。例如,内置性能计数器可能为给定度量值提供最小值、平均值和最大值,但它可能缺少90%分位数。如果你决定在代码成熟时关心95%和99%的百分位呢?更别提PCW将提供的任何统计信息都硬编码到特定的时间间隔。为了在分析中获得真正的灵活性,我们显然需要将数据聚合推迟到实际分析,而不是尝试预测我们在运行时需要什么数据。
这并不是说PCW应该被忽视。虽然缺乏一些列出的领域,但它仍然提供了足够的价值,使我们在性能工程方面获益。由于本书的重点是诊断,因此对PCW技术的详细描述不在本书的范围之内。不过,我们将在整本书中酌情提到PCW,以适用于其优势可以有效应用的场景。
注意:请记住,性能工程可以侧重于提高响应性和/或效率。考虑以下示例,其中PCW和ETW用于实现这些目标:
交互响应能力
测量时汇总:PCW –例如最小、最大和平均响应延迟
- 不变的
- 没有好的工具支撑
- 可以监控资源使用情况的近似值,但无法与用户交互关联
分析时汇总: ETW -例如每个交互的开始/停止事件
- 灵活的
- 工具化(属性)用户交互可以与资源使用相关
效率: 资源使用率
测量时汇总: PCW --例如处理器用途、磁盘时间
-
好工具
-
远程收集
-
告警
-
DBMS集成
-
大时间跨度
-
缺乏调用堆栈可见性,无法将资源使用情况与相应的消费者和活动联系起来
分析时汇总: ETW--例如磁盘IO的启停,上下文切换、CPU采样事件
- 用于本地捕获和分析的优秀工具
- 不太使用远程收集
- 能够使用调用堆栈识别负责特定资源使用的用户和活动
PCW和ETW的互补优势使它们成为两种共生类型的性能反馈系统的良好候选者,我们将在下一节中回顾这些系统。
监控 vs 诊断(Monitoring vs. Diagnostics)
在大多数对跟踪和提高产品性能感兴趣的组织中,出现了两个互补的流程:
监控--持续(即7*24小时)跟踪关键业绩指标,目标是:
-
确保监测指标达到和/或超过目标响应性、流动性和/或效率目标(性能目标)
-
在适当的优先级和严重程度上出现目标违反和回归事件
诊断--按需(例如及时、基于触发、基于升级等)对关键系统和用户活动进行测量,目标是对通过监控出现的问题进行根本原因分析。
监控通常涉及跟踪较长的时间段(跨越小时的时间段)。监控通常侧重于低频活动(例如1Hz以下),持续时间为一分钟或更长。示例包括
-
聚合吞吐量(例如每分钟平均/峰值操作)
-
每分钟平均使用率(例如CPU使用率、磁盘使用率)
收集的数据通常足够小,可以以业务可接受的成本保留数周甚至数月的数据,从而了解质量从一天到一天、一周到一周、月到月、发布到发布的趋势。
另一方面,当问题浮出水面时,诊断就会发挥作用——通常是一个需要快速有效补救的高概率问题。这些问题可以通过测试(合成工作负载)或监控(遥测)主动地浮出水面,甚至可以由最终用户被动地浮出水面。考虑到诊断大多数性能问题需要大量数据,因此需要收集更多数据才能成功进行根本原因分析。
为诊断收集的数据通常跨越几分钟,在此期间跟踪高频活动(远高于1KHz)。此类活动通常具有亚秒级的持续时间(例如,单个磁盘I/O)。鉴于收集的测量结果的丰富性,由此产生的数据量可能是巨大的。因此,长时间保留它们可能相当昂贵,需要实施谨慎的保留策略,以避免不必要的资源浪费
注意:限制诊断测量期间收集的数据量的一个常见缓解措施是依赖循环日志记录技术,在这种技术中,特定大小的缓冲区以循环方式预先分配和覆盖。这样,仅保留最新的测量值(未覆盖)。
注意:在评估监控和诊断反馈系统的效率时,有几个关键指标。具体来说,检测时间(time to detection,简称TTD)是有效监控的关键指标,而导致时间(time to cause,简称TTC)和补救时间(time to remediation, 简称TTR)是有效诊断的关键指标。这两个反馈系统的一个共同指标是缓解时间(time to mitigation, 简称TTM)。典型的时间线是TTD→TTC→TTM→TTR,即您检测到,然后是根本原因,然后是缓解,然后是根因(译者注:这里应该是补救吧?)。请注意,有些问题可以在没有根本原因的情况下缓解,但要补救问题,您必须首先确定根本原因。
我们已经提到,监控通常是通过PCW实施的。这是否意味着ETW做了一个糟糕的平台来实现监控?一点也不。您可以使用PCW构建的任何反馈系统也可以构建在ETW之上(请注意,情况并非如此)。事实上,ETW的结果可能会更有效。不过,PCW更早出现,在PCW之上构建的所有众多性能监控工具也是如此,包括与数据库的集成,这些工具提供了在监控领域的丰富的商业智能可能性——尤其是在服务器端。有许多性能指标可以通过PCW有效监控,并提供足够的工具支持。
然而,在这本书中,我们主要关注有效诊断的方法论,只是顺便提到监控反馈系统。在性能领域,市场上存在多种监控方法。讨论这些问题超出了本书的范围。
数据收集方法
收集性能数据有一些补充办法。让我们在本节中回顾一下它们。
数据发现和汇总方式
正如我们刚才在PCW与ETW的讨论中看到的,从概念上讲,收集性能数据有两种方法。具体来说,数据收集可以遵循拉式模型,也可以遵循推式模型。在拉取模型中,数据会定期查询,而在推送模型中,每次发生状态转换时都会记录数据。收集的数据可以是瞬时的(例如当前温度),也可以是累积的(例如整个拖后时间段的平均温度)。
注:表2.5说明了推拉数据收集模型的几个示例,描述了当与表示时间点的即时值或在时间间隔内聚合的累积测量一起使用时的场景:
数据 | 推式 | 拉式 |
---|---|---|
瞬时值(时间点) | 上下文切换和磁盘IO ETW检测 | CPU采样分析、采样进程工作集ETW检测、一些PCW计数器(例如处理器驻留状态) |
累积值 | 紧凑型上下文切换(译:没看懂)ETW检测 | 大多数PCW计数器(例如CPU利用率) |
推拉模式都有其优缺点。类似地,瞬时值和累积值在实际性能工程应用中都有用途
抽样与归因
在性能分析的上下文中查看拉式和推式模型的另一种有趣的方法是考虑性能数据是如何生成的。存在两种主要方法:
-
采样(Sampling)是周期性或偶发状态集合,后来被用于通过近似统计来度量活动
-
归因(Attribution)是通过精确的事件划定特定的活动,后来被用于精确统计确切发生的事件来度量活动
译者注: 没咋看懂
请注意,采样是拉取模型的示例(数据在采样发生时拉取),而归因是推取模型的示例(数据在事件发生时推出)。
把这些新术语应用到PCW和ETW的角度来看的话,PCW数据在完全由消费者定义的时间表上通过轮询进行采样得到,PCW的数据汇聚在生产者端,它低频监控用户定义的数据。相反,ETW数据通过生产者在事件发生时推送事件得到,数据的聚合在消费者这端,ETW提供对诊断中通常必要的高频数据的访问(归因)。
定期提取数据的行为通常被称为轮询。正如我们将在第7章中看到的,基于轮询的性能数据收集的一个示例是基于样本的CPU分析,其中CPU使用情况(默认情况下)每毫秒采样一次。
注意:具体来说,CPU采样分析的工作原理是定期查询处理器指令指针位置并将其映射回代码。使用这些采样数据,人们可以重新创建一个相当准确的图片,说明在程序中的时间花费。
采样的一个显著优点是,它不需要对正在运行的程序代码进行任何修改,而且通常不会过于侵入性。与采样不同,归因需要修改代码,并涉及重新启动正在诊断的程序。
注意:程序中的自定义活动的归因需要对相应的程序进行更改。操作系统活动(如上下文切换和磁盘I/O)的归属可在任何时间点按需提供,因为这些活动已经在Windows中进行了检测
归因的一个显著优点是它提供了高精度的测量。另一方面,通过抽样获得的数据本质上是不显眼的,它可能会忽略其两个相邻样本之间发生的活动。另一方面,归因只捕获状态转换,并且可能会错过在这些转换之间发生的活动,而采样通常仍然可以获得足够好的近似值。我们将在第7章中使用CPU作为案例研究,对比这两种互补的测量方法。
请注意,归因可能会导致生成比采样更多的性能数据。在抽样的情况下,数据量与抽样率成正比,而在归因的情况下,数据量与归属活动的数量成正比。
关键点回顾(Key takeaways)
来回顾下我们迄今所学到的内容,Windows提供了几种用于性能监视和诊断的内置工具:任务管理器、资源监视器和性能监视器。对于CPU占用率分析来讲:
任务管理器
- 帮助清点正在运行的程序,并识别那些消耗大量系统资源的程序
- 不提供记录和离线分析功能,使其用途仅限于帮助识别持续的饱和问题
资源监视器
-
记录过去60秒的资源活动
-
与任务管理器类似,不提供记录工具和离线分析功能,使其用途仅限于帮助在执行的最后一分钟内识别持续的饱和问题
-
比任务管理器提供更多的系统活动可视性
性能监视器
-
与任务管理器和资源监视器不同,支持通过使用用户定义的数据收集器集捕获的BLG文件进行离线分析
-
允许在离线分析中跟踪新启动的进程
-
在近乎实时的可视化分析中,仅显示在PerfMon之前启动的进程的活动
Windows提供了两个用于记录和收集性能数据的互补基础设施:PCW和ETW。这两个平台已经发展到分别涵盖监控和诊断反馈系统。
PCW
- 完全由消费者定义策略,通过轮询进行数据采样
- 提供对在生产者一侧聚合的低频数据的监控访问
- PerfMon是最常见的Windows工具,用于收集PCW数据以及在线和离线可视化
- 通过BLG文件启用PCW离线分析
ETW
- 数据由生产者在事件发生时推送,所有聚合都发生在消费者侧
- 提供对诊断中经常需要的高频数据的访问
- WPR是收集ETW性能跟踪的首选工具,而WPA是基于ETW的进行性能诊断分析的优秀工具
- 通过ETL文件启动ETW离线分析
这两个平台都可以有效地分析某些类型的性能问题的根本原因,但ETW在大多数情况下在诊断方面占上风。PCW在大多数监测情况下仍然可以非常有效。
由于这本书主要涉及教您如何诊断性能问题,我们将把大部分注意力都花在ETW上。正如我们提到的,ETW比PCW提供了更多的分析灵活性,特别是当您需要对收集的数据执行非平凡分析时。在下一章中,我们将向您展示如何在Windows上使用WPR进行基于ETW的性能测量。
【Fundamentals of Windows Performance Analysis】翻译,第二章:性能测量&分析概述