Sun Studio 12:性能分析器

基于时钟的分析

基于时钟的分析的事件特定数据由分析间隔计数的数组组成。在 Solaris OS 上,提供了间隔计数器。在分析间隔结束时,相应的间隔计数器加 1,并安排另一个分析信号。仅当 Solaris LWP 线程进入 CPU 用户模式时,才记录和重置数组。重置数组包括将用户 CPU 状态的数组元素设置为 1,将所有其他状态的数组元素设置为 0。在重置数组之前,进入用户模式时会记录数组数据。因此,数组包含在自上次进入用户模式以来进入的每个微态的计数累积(内核为每个 Solaris LWP 维护十个微态)。在 Linux OS 上,不存在微态;唯一的间隔计数器是“用户 CPU 时间”。

在记录数据的同时记录调用栈。如果在分析间隔结束时 Solaris LWP 未处于用户模式,则在 LWP 或线程再次进入用户模式之前调用栈无法更改。因此,调用栈总是会在每个分析间隔结束时准确记录程序计数器的位置。

Solaris OS 上每个微态所服务于的度量表 7–2 所示。

表 7–2 内核微态如何服务于度量

内核微态 

说明 

度量名称 

LMS_USER

在用户模式下运行 

用户 CPU 时间 

LMS_SYSTEM

在系统调用或缺页时运行 

系统 CPU 时间 

LMS_TRAP

在出现任何其他陷阱时运行 

系统 CPU 时间 

LMS_TFAULT

在用户文本缺页时休眠 

文本缺页时间 

LMS_DFAULT

在用户数据缺页时休眠 

数据缺页时间 

LMS_KFAULT

在内核缺页时休眠 

其他等待时间 

LMS_USER_LOCK

等待用户模式锁定时休眠 

用户锁定时间 

LMS_SLEEP

由于任何其他原因而休眠 

其他等待时间 

LMS_STOPPED

已停止(/proc、作业控制或 lwp_stop

其他等待时间 

LMS_WAIT_CPU

等待 CPU 

等待 CPU 时间 

计时度量的准确性

计时数据是基于统计收集的,因此易于出现任何统计抽样方法的所有误差。对于时间非常短的运行(仅记录少量分析数据包),调用栈可能不能表示程序中使用大多数资源的各部分。因此应以足够长的时间或足够多的次数运行程序,以累积感兴趣的函数或源代码行的数百个分析数据包。

除了统计抽样误差外,收集和归属数据的方式以及程序在系统中前进方式也会引起特定的误差。以下是计时度量可能出现不准确或失真的一些情况:

除了刚刚介绍的不准确外,计时度量还会因收集数据的过程而失真。记录分析数据包所用的时间从不出现在程序的度量中,因为记录是由分析信号启动的。(这是相关性的另一个实例。)记录过程中所用的用户 CPU 时间在所记录的任何微态之间分配。结果是对用户 CPU 时间度量过少记帐,而对其他度量过多记帐。记录数据所用的时间量通常不到缺省分析间隔的 CPU 时间的百分之几。

计时度量的比较

如果将通过在基于时钟的实验中进行分析所获得的计时度量与通过其他方式获得的时间进行比较,则应该注意以下问题。

对于单线程应用程序,为进程记录的 Solaris LWP 或 Linux 线程时间总计通常精确到千分之几(与同一进程的 gethrtime(3C) 返回的值相比)。CPU 时间可能与由同一进程的 gethrvtime(3C) 返回的值相差几个百分点。如果负载过重,则差异可能更加明显。但是,CPU 时间差异并不表示系统失真,并且为不同函数、源代码行等报告的相对时间也不会显著失真。

对于 Solaris OS 上使用未绑定线程的多线程应用程序,gethrvtime() 所返回的值的差异可能没有意义,因为 gethrvtime() 返回 LWP 的值,而线程可能随 LWP 的不同而不同。

性能分析器中报告的 LWP 时间可能与 vmstat 报告的时间有很大差异,因为 vmstat 报告 CPU 的汇总时间。如果目标进程具有的 LWP 比它所运行的系统具有的 CPU 多,则性能分析器显示的等待时间比 vmstat 报告的长。

出现在性能分析器的“统计”标签和 er_print 统计显示中的微态计时基于进程文件系统 /proc 使用报告,因此微态中所用时间的记录具有很高的准确性。有关更多信息,请参见 proc (4) 手册页。可以将这些计时与 <Total> 函数(它将程序作为一个整体表示)的度量进行比较,以获取聚集计时度量的准确性指示。但是,“统计”标签中显示的值可能包含其他基值,而 <Total> 的计时度量值中不包含这些基值。这些基值来自暂停数据收集的时间段。

用户 CPU 时间和硬件计数器循环时间是不同的,因为在将 CPU 模式切换到系统模式时会关闭硬件计数器。有关更多信息,请参见陷阱