Oracle Solaris Studio 12.4 Man Pages

Exit Print View

Updated: January 2015
 
 

collect(1)

Name

collect - 用于收集程序性能数据的命令

Synopsis

collect collect-arguments target target-arguments
collect
collect -V

Description

collect 命令会运行目标进程并记录该进程的性能数据和全局数据。性能数据使用分析或跟踪技术进行收集。可以使用 GUI 程序 (analyzer) 或命令行程序 (er_print) 检查数据。我们在此将 collect 命令运行的数据收集软件称为“收集器”。

运行 collect 命令一次所产生的数据称为一次实验。实验在文件系统中以一个目录进行表示,该目录中包含多个文件。

target 是您要收集性能数据的可执行文件、Java(TM) .jar 文件或 Java .class 文件的路径名称。(有关 Java 分析的更多信息,请参见下文的“Java 分析”。)collect 命令的目标可执行文件可以使用任何级别的优化进行编译,但必须使用动态链接。如果静态链接程序,则 collect 命令会输出一条错误消息。要使用 analyzerer_print 查看带注释的源代码,应该使用 -g 标志编译目标,并且不应剥离目标。

要启用数据空间分析,可执行文件应使用 -xhwcprof -xdebugformat=dwarf -g 标志进行编译。这些标志适用于使用 C、C++ 和 Fortran 编译器进行编译,但 -xhwcprof 标志仅在 SPARC[R] 平台上有意义,在其他平台上会被忽略。如果不使用这些标志编译可执行文件,则 er_print 中的 data_layoutdata_singledata_objects 命令不会显示数据。即使目标未使用 -xhwcprof 标志编译,内存对象报告也会显示数据。请参见下文的“数据空间分析”部分。

collect 命令使用以下策略来查找其目标:

  • 如果具有指定目标名称的文件存在、拥有执行权限集且是 ELF 可执行文件,则 collect 命令会验证该文件是否可以在当前计算机上运行,然后运行该文件。如果该文件不是 ELF 可执行文件,则 collect 命令会假定它是脚本并运行该文件。

  • 如果具有指定目标名称的文件存在但没有执行权限,则 collect 会检查该文件是否为 Java[TM] jar 文件(目标名称以 .jar 结尾)或类文件(目标名称以 .class 结尾)。如果该文件是 jar 文件或类文件,则 collect 会使用任何必要的标志插入 Java[TM] 虚拟机 (JVM) 软件作为目标,并收集该 JVM 计算机上的数据。(术语“Java 虚拟机”和 "JVM" 表示用于 Java[TM] 平台的虚拟机。)请参见下文有关“Java 分析”的部分。

  • 如果未找到具有指定目标名称的文件,则 collect 将搜索路径以查找可执行文件;如果找到可执行文件,则 collect 将按如上所述进行验证。

  • 如果在您的路径中也未找到具有目标名称的文件,则该命令会搜索附加了该名称和 .class 字符串的文件;如果找到具有该类名称的文件,则 collect 会按上面所述使用适当的标志插入 JVM 计算机。

  • 如果上述所有过程都找不到目标,则命令失败。

Options

如果执行无参数调用,collect 将输出用法摘要,其中包含实验的缺省配置。

如果仅使用 -h 参数调用,则 collect 会输出硬件计数器信息。如果处理器支持硬件计数器溢出分析,则 collect 会输出两个包含硬件计数器相关信息的列表。第一个列表包含“别名”硬件计数器;第二个列表包含“原始”硬件计数器。输出还包含该处理器的缺省 HWC 实验的规范。有关更多详细信息,请参见下文的“硬件计数器溢出分析”部分。

如果处理器不支持硬件计数器溢出处理,输出会进行说明。

数据规范

-p option

收集基于时钟的分析数据。option 的允许值包括:

off

关闭基于时钟的分析

on

打开缺省分析间隔大约为 10 毫秒的基于时钟的分析。

lo[w]

打开分析间隔大约为 100 毫秒(低精度)的基于时钟的分析。

hi[gh]

打开分析间隔大约为 1 毫秒(高精度)的基于时钟的分析。

n

打开基于时钟的分析并将分析间隔设置为 nn 值可以是整数或浮点数,并加上后缀 u 表示微秒值,或加上后缀 m 表示毫秒值。如果不使用后缀,则假定值以毫秒为单位。

如果值小于时钟分析最小值,则将其设置为最小值;如果值不是时钟分析精度的倍数,则向下舍入为最接近的时钟分析精度倍数。如果值超过时钟分析最大值,将会报告错误。如果值为负数或零,将会报告错误。

如果未指定显式 -p 参数,也未指定计数数据、争用检测数据或死锁数据,则会打开基于时钟的分析。如果指定了 -h high-h low,以在高频率或低频率下请求该芯片的缺省计数器集,则缺省的时钟分析也将设置为高频率或低频率;将遵从显式 -p 参数。

不再支持基于时钟分析的数据空间和内存空间分析;所有受支持的计算机都有硬件计数器用于内存操作。

-h parameter

收集硬件计数器溢出 (HWC) 分析数据。参数可以是以下任意值:

off

不收集任何硬件计数器分析数据。如果指定了 off,则不能指定任何其他 -h 参数。如果指定了任何其他值,则可以指定多个 -h 参数并使用各个参数的计数器。

on

使用为特定系统定义的缺省计数器集。该集会显示在 collect -h 的输出中。并非所有系统都定义了缺省计数器集;如果未定义该集,-h on 会生成一个错误。

hi|high

使用为特定系统定义的缺省计数器集,但是以高速率分析。并非所有系统都定义了缺省计数器集;如果未定义该集,-h hi 会生成一个错误。

lo|low

使用为特定系统定义的缺省计数器集,但是以低速率分析。并非所有系统都定义了缺省计数器集;如果未定义该集,-h lo 会生成一个错误。

ctr_def...[,ctr_n_def]

使用一个或多个指定计数器收集硬件计数器溢出分析数据。支持的最大计数器数量(ctr_defctr_n_def)取决于处理器。您可以确定用于分析当前计算机的最大硬件计数器定义数量,并在当前计算机上运行不带任何其他参数的 collect -h,以查看可用硬件计数器及缺省计数器集的完整列表。

每个计数器定义都采用以下格式:

[+|-]ctr[~attr=val]...[~attrN=valN][/reg#],[interval]

计数器定义选项的含义如下所示:

+|-

可应用于内存相关计数器的可选参数。+ 要求记录数据空间和内存空间分析数据。- 要求不进行记录。

内存相关计数器是指类型为 loadstoreload-store 的计数器;在运行不带任何其他命令行参数的 collect -h 命令时获取的计数器列表中会显示类型。某些这类计数器还带有 precise 标签。

对于 SPARC 或 x86 上的精确计数器,不需要 +;缺省情况下,将记录数据空间和内存空间数据。- 将关闭数据空间和内存空间数据。

仅对于 SPARC,在非精确内存计数器上指定 + 会导致 collect 通过查找触发溢出的指令以及内存引用的虚拟和物理地址来收集数据空间数据。缺省情况下,不会记录此类数据,因此不需要使用 - 来将其关闭。请参见下文的“数据空间和内存空间分析”部分。

ctr

特定于处理器的计数器名称。您可以运行不带任何其他命令行参数的 collect -h 命令来确定计数器名称列表。在大多数系统上,即使未列出某计数器,仍可使用数值指定该计数器;指定的数值为十六进制(0x1234) 或十进制。早期芯片的驱动程序不支持数值,但近期芯片的驱动程序支持。以数字方式指定计数器时,也应该指定寄存器号。要使用的数值可在芯片特定制造商的手册中找到。手册名称在 collect -h 输出中指定。有些计数器仅在专有供应商手册中进行介绍。

~attr=val

可选的一个或多个属性选项。在某些处理器上,可以将多个属性选项与一个硬件计数器关联。如果处理器支持多个属性选项,则运行不带任何其他命令行参数的 collect -h 也会列出要用于 attr 的属性名称。值 val 可以采用十进制或十六进制格式。十六进制格式的数字使用 C 程序格式,其中的数字前置了零和小写 x (0xhex_number)。大多数属性都与计数器名称串联。每个 attr 名称前必须有 ~

/reg#

要用于计数器的硬件寄存器。如果未指定寄存器,则 collect 会尝试将计数器放入第一个可用的寄存器,因此,可能由于寄存器冲突而无法放置后续计数器。如果指定了多个计数器,则这些计数器必须使用不同的寄存器。通过运行不带任何其他命令行参数的 collect -h 命令,您可以查看允许的寄存器号列表。如果指定了寄存器,则必须使用 / 字符。

interval

通过定义计数器溢出值设置的抽样频率。有效值如下:

on

使用某一缺省速率,尝试与缺省时钟分析速率(100x/秒)的分析解析匹配。在 Solaris 中,HWC 速率可在运行时调节,以响应密集型工作负荷。在 Linux 中,速率将保持固定。因此,缺省值对于某些原始计数器而言,可能并非适合的选择。

hi

将间隔设置为 on 的约十分之一长。

lo

将间隔设置为 on 的约 10 倍长。

value

将间隔设置为特定值(以十进制或十六进制格式指定)。设置数值时要小心,特别是将间隔设置过低会重载应用程序或者甚至整个系统。根据我们的经验,每秒每个线程应少于 1000 个事件。

可以省略间隔,在这种情况下将使用 on 的值。即使省略间隔,也需要在它前面加上逗号(-h 参数中的最后一个计数器除外)。

对于原始计数器,hiloon 的值是猜测值,但是对于任何特定程序,很难猜测适当的间隔。如果为任何原始计数器指定 on/hi/lo,并且事件分别快于每线程每秒 100/1000/10,则会将间隔向下调节为 Oracle Solaris 系统上更合理的最大值。

示例:一些有效的 -h 用法示例:

 
-h on
-h lo
-h hi
    Enable the default counters with default, low, or
    high rates, respectively

-h cycles,,insts,,+dcm
-h cycles -h insts -h +dcm
  Both have the same meaning: three counters: cycles, insts 
  and dataspace-profiling of D-cache misses (SPARC only)

-h cycles~system=1
  Count cycles in both user and system modes

-h 0xc0/0,10000003
On Nehalem, that is the equivalent to
-h inst_retired.any_p/0,10000003

一些有效的 -h 用法示例:

 
-h cycles -h off
  Can't use off with any other -h arguments
-h cycles,insts
  Missing comma, and "insts" does not parse as a number for 
  <interval>

如果 -h 参数指定使用硬件计数器,但硬件计数器在命令发出时正由其他参数使用,则 collect 命令将报告错误,且不会运行实验。

如果未指定 -h 参数,则不收集硬件计数器分析数据。一个实验可以同时指定硬件计数器溢出分析和基于时钟的分析。指定硬件计数器溢出分析不会禁用基于时钟的分析(即使已缺省启用)。

有关硬件计数器的更多信息,请参见下文的“硬件计数器溢出分析”部分。

-s option

收集同步跟踪数据。

跟踪事件的最小延迟阈值使用 option 进行设置。option 的允许值包括:

on

打开同步延迟跟踪并在运行时通过校准来设置阈值

calibrate

on 相同。

off

关闭同步延迟跟踪

n

打开同步延迟跟踪并将阈值设置为 n 微秒;如果 n 为零,则跟踪所有事件

all

打开同步延迟跟踪并跟踪所有同步事件

缺省情况下,会关闭同步延迟跟踪。

在 Solaris 上,跟踪以下函数:mutex_lock()rw_rdlock()rw_wrlock()cond_wait()cond_timedwait()cond_reltimedwait()thr_join()sema_wait()pthread_mutex_lock()pthread_rwlock_rdlock()pthread_rwlock_wrlock()pthread_cond_wait()pthread_cond_timedwait()pthread_cond_reltimedwait_np()pthread_join()sem_wait()

在 Linux 上,会跟踪以下函数:pthread_mutex_lock()pthread_cond_wait()pthread_cond_timedwait()pthread_join()sem_wait()

对于 Java 程序,将记录用户代码中 Java 监视器的同步事件,而不会记录 JVM 计算机内的本机同步调用。

-H option

收集堆跟踪数据。option 的允许值包括:

on

打开对内存分配请求的跟踪

off

打开对内存分配请求的跟踪

缺省情况下,会关闭堆跟踪。

记录所有本机调用的堆跟踪事件。将对 mmap 的调用视为内存分配。

对于 Java 程序,不支持堆分析。指定将其视为一个错误。

请注意,堆跟踪可能会生成非常大的实验。此类实验的装入和浏览速度都非常慢。

-i option

收集 I/O 跟踪数据。option 的允许值包括:

on

打开对 I/O 操作的跟踪

off

关闭对 I/O 操作的跟踪

缺省情况下,关闭 I/O 操作。

请注意,I/O 跟踪可能会生成非常大的实验。此类实验的装入和浏览速度都非常慢。

-M option

指定对 MPI 实验的收集。(请参见下文的“MPI 分析”。)collect 的目标应为 mpirun,且其参数应当通过插入的 -- 参数与用户目标(即 mpirun 要运行的程序)分隔。实验按惯常方式命名且称为”创始实验“,其目录包含每个 MPI 进程的子实验,按等级进行命名。建议始终将 -- 参数与 mpirun 一起使用,以便可以通过将 collect 及其选项前置于 mpirun 命令行来收集实验。

option 的允许值包括:

MPI-version

打开 MPI 实验的收集功能并假定指定的 MPI 版本。当您键入不带任何参数的 collect 时或响应使用 -M 指定的无法识别的版本时,将输出识别的 MPI 版本。

off

关闭对 MPI 实验的收集。

缺省情况下,关闭对 MPI 实验的收集。打开 MPI 实验时,-m 的缺省设置(请参见下文)将更改为 on

-m option

收集 MPI 跟踪数据。(请参见下文的“MPI 分析”。)

option 的允许值包括:

on

打开 MPI 跟踪信息。

off

关闭 MPI 跟踪信息。

缺省情况下会关闭 MPI 跟踪,除非启用了 -M 标志,在这种情况下会缺省打开 MPI 跟踪。通常使用 -M 收集 MPI 实验,无需用户对 MPI 跟踪进行控制。如果要收集 MPI 实验,但不收集 MPI 跟踪数据,您可以使用显式标志:

-M MPI-version -m off
-c option

收集计数数据。option 的允许值包括:

on

打开计数数据。

static

在假定每个指令执行了一次的情况下,打开模拟计数数据。

off

关闭计数数据。

缺省情况下,关闭计数数据。计数数据不能和任何其他类型的数据一起收集。对于计数数据或模拟计数数据,将对已检测并静态链接的可执行文件及任何共享对象进行计数;对于计数数据而不是模拟计数数据,还会对动态装入的共享对象进行检测和计数。

在 Solaris 上,不需要特殊的编译,尽管计数选项与编译标志 -p-pg-qp-xpg-xlinkopt 不兼容。在 Linux 上,可执行文件必须使用 -annotate=yes 标志进行编译,才能收集计数数据。

-I directory

为计数数据检测指定目录。

-N libname

指定要从计数数据检测中排除的库,不管该库是链接到可执行文件还是使用 dlopen (3C) 装入。可以指定多个 -N 选项。

-r option

为线程分析器收集数据争用检测或死锁检测数据。

option 的允许值包括:

race

收集数据以检测数据争用。

deadlock

收集数据以检测死锁和可能的死锁。

all

收集数据以检测数据争用、死锁和可能的死锁。也可以指定为 race,deadlock

off

关闭对数据争用、死锁和可能的死锁的数据收集。

on

收集数据以检测数据争用(与 race 相同)。

terminate

如果检测到不可修复的错误,将终止目标进程。

abort

如果检测到不可修复的错误,则终止带有信息转储的目标进程。

continue

如果检测到不可修复的错误,将允许进程继续。

缺省情况下,关闭对所有线程分析器数据的收集。

terminateabortcontinue 选项可添加到任何数据收集选项,并控制发生不可修复的错误(例如,实际(而不是潜在)死锁)时的行为。缺省行为是 terminate

线程分析器数据不能与任何跟踪数据一起收集,但可以与时钟或硬件计数器分析数据一起收集。线程分析器数据会明显减缓目标执行速度,且分析数据可能对用户代码没有意义。

可以使用 analyzertha 对线程分析器实验进行检查。后者会显示简化的缺省标签列表,但其实是一样的。

要启用数据争用检测,必须在编译时或通过调用后处理程序来检测可执行文件。如果未检测目标,也未检测其库列表中的任何共享对象,则会显示一个警告,但会运行实验。其他线程分析器数据不需要检测。

有关更多详细信息,请参见 tha (1) 手册页或Thread Analyzer User's Guide

-S interval

以指定的间隔(秒)收集定期样例。记录进程中的数据抽样,并包括内核中的时间戳和执行统计信息等内容。interval 的允许值包括:

off

关闭定期抽样功能。

on

打开使用缺省抽样间隔(1 秒)的定期抽样功能。

n

打开抽样间隔为 n 秒的定期抽样功能;n 必须是正数。

缺省情况下,会打开定期抽样功能。

如果未提供数据规范参数,将使用缺省精度收集基于时钟的分析数据。

如果已显式禁用基于时间的分析,且未启用硬件计数器溢出分析或任何类型的跟踪,则会显示警告说明未收集函数级别的数据,然后执行目标并记录全局数据。

实验控制

-L size

将记录的分析和跟踪数据量限制为 size MB。该限制适用于所有分析数据量和跟踪数据量之和,但不适用于抽样点。该限制只是近似值,可以被超出。当达到该限制时,不再记录分析和跟踪数据,但实验会一直保持打开状态并记录抽样,直到目标进程终止。size 的允许值包括:

unlimitednone

不对实验强加大小限制。

n

强加 n MB 限制。n 的值必须为正数(大于零)。

缺省情况下,记录的数据量不存在限制。

-F option

控制是否应当记录子孙进程的数据。(始终会收集创始进程中的数据,这和任何 -F 设置无关。)option 的允许值包括:

on | all

针对所有子孙进程记录实验。

off

不针对任何子孙进程记录实验。

=<regex>

针对可执行文件名称(a.out 名称)与正则表达式匹配的子孙进程记录实验。仅使用可执行文件的基名而不是完整路径。如果您使用的 <regex> 包含空白或 shell 解释的字符,请务必将完整的 =<regex> 参数括在单引号内。

缺省情况下,会针对所有子孙进程记录实验。有关更多详细信息,请阅读下文的“跟踪子孙进程”和“分析脚本”部分。

-A option

控制是否应将目标进程使用的装入对象归档或复制到记录的实验中。option 的允许值包括:

on

将装入对象(目标以及其使用的任何共享对象)复制到实验中。也会复制任何 .anc 文件和 .o 文件,这些文件的 Stabs 或 DWARF 信息不在装入对象中。

src

除了像 -A on 中一样复制装入对象,还将可找到的所有源文件和 .anc 文件复制到实验中。

used[src]

除了像 -A on 中一样复制装入对象,还将记录的数据中引用的和可找到的所有源文件和 .anc 文件复制到实验中。

off

不将装入对象或源文件复制或归档到实验中。

如果您将实验复制到另一台计算机,或者从另一台计算机读取实验,请指定 -A on。这样做将消耗更多磁盘空间,但可允许在其他计算机上读取实验。

请注意,-A on 不会复制任何源文件或对象文件 (.o);您需要自己确保可从检查实验的计算机访问这些文件,并且在记录实验后未更改或重建这些文件。

在收集时归档实验(尤其是包含许多子孙进程的实验)可能代价很高。比较好的策略是使用 -A off 收集数据,然后在运行终止后使用 -s 标志运行 er_archive (1) 。

-A 的缺省设置为 on

-j option

在目标为 JVM 计算机时控制 Java 分析。option 的允许值包括:

on

记录 JVM 计算机的分析数据,并识别 Java HotSpot[TM] 虚拟机编译的方法以及记录 Java 调用堆栈。

off

不记录 Java 分析数据。

<path>

记录 JVM 的分析数据并使用在 <path> 中安装的 JVM。

请参见下文的“Java 分析”部分。

如果目标是 JVM 计算机,必须使用 -j on 才能获取分析数据。如果目标是类文件或 jar 文件,则不需要 -j on 选项。如果使用 64 位 JVM 计算机,您必须将其路径显式指定为目标;对于 32 位 JVM 计算机,请勿使用 -d64 选项。如果指定了 -j on 选项,但目标不是 JVM 计算机,可能会向目标传递一个无效参数,且不会记录任何数据。collect 命令将验证为 Java 分析指定的 JVM 计算机的版本。

-J java_arg

指定要传递到用于分析的 JVM 的其他参数。如果指定了 -J,则启用 Java 分析 (-j on)。如果其中包含多个参数,必须使用引号将 java_arg 引起来。其中包含一组以空白或制表符分隔的令牌;每个令牌作为一个独立的参数传递至 JVM。注意:JVM 的大多数参数必须以 "-" 字符开头。

-l signal

每当有给定信号传递到进程时记录抽样点。

有关选择信号的更多信息,请参见下文的“数据收集和信号”部分。

-y signal[,r]

使用 signal(称为暂停-恢复信号)控制数据记录。在有给定信号传递到进程时,在暂停状态(不记录数据)和恢复状态(记录数据)之间切换。如果指定了可选的 ,r 标志,会以恢复状态启动,否则会以暂停状态启动。该选项不影响抽样点的记录。

暂停-恢复信号的一个用途是在不收集数据的情况下启动一个目标,让其达到稳定状态,然后再启用数据。

有关选择信号的更多信息,请参见下文的“数据收集和信号”部分。

输出控制

-o experiment_name

使用 experiment_name 作为要记录的实验的名称。experiment_name 必须以 .er 字符串结尾;否则,将输出错误消息且不会运行实验。

如果不指定 -o 选项,则为实验提供一个格式为 stem.n.er 的名称,其中 stem 是字符串,n 是数字。如果使用 -g 选项指定了组名称,则将 stem 设置为不带 .erg 后缀的组名称。如果未指定组名称,则将 stem 设置为字符串 "test"。

如果从用于运行 MPI 作业的命令之一(例如 mpirun)调用,但不带 -M MPI-versions 且未指定 -o,则采用用于定义该进程的 MPI 等级的环境变量的名称中使用的值 n。否则,将 n 设置为比当前使用的最大整数还要大的值。(请参见下文的“MPI 分析”。)

如果没有使用 stem.n.er 格式指定名称,而正在使用给定名称,将输出一条错误消息且不会运行实验。如果名称采用 stem.n.er 格式且正在使用提供的名称,将在与比当前使用的 n 最大值还要大的值对应的名称下记录实验。如果名称已更改,则会显示一条警告。

-d directory_name

将实验置于 directory_name 目录中。如果未指定目录,会将实验放置在当前的工作目录中。如果指定了组(请参见下文的 -g),该组文件也将写入 -d 指定的目录中。

对于最轻量的数据收集,最好使用 -d 指定存放数据的目录,以便将数据记录到本地文件。但是,对于群集上的 MPI 实验,创始实验必须在相同的路径下对所有进程可用,以便将所有数据记录到创始实验中。

写入长延迟文件系统的实验问题尤为突出,可能进行非常缓慢,特别是在收集样例数据时(缺省采用 -S on)。如果必须通过长延迟连接来进行记录,请禁用样例数据。

-g group_name

将实验添加到实验组 group_namegroup_name 字符串必须以 .erg 字符串结尾;否则,将报告错误且不运行实验。组文件的第一行必须包含字符串

#analyzer experiment group

且后面的每一行都是一个实验的名称。

-O file

collect 的所有输出附加到指定的文件,但不会重定向以下各项的的输出:产生的目标、dbx(使用 -P 参数调用)或记录计数数据中涉及的进程(使用 -c 参数调用)。如果 file 设置为 /dev/null,则抑制 collect 的所有输出(包括任何错误消息)。

-t duration

收集指定时长的数据。duration 可以是单个数字(后跟 m 指定分钟或后跟 s 指定秒(缺省值)),也可以是以 - 符号分隔的两个这样的数字。如果指定一个数字,将从开始运行时开始收集直到给定时间;如果指定两个数字,将从第一个时间开始收集数据,到第二个时间结束。如果第二个时间为零,将开始收集数据,直到该程序运行结束。如果指定了两个非零数字,则第一个数字必须小于第二个数字。

其他参数

-P <pid>

编写 dbx 脚本以附加到具有给定 PID 的进程,从中收集数据,然后使用该脚本调用 dbx。可以指定时钟或硬件计数器分析数据,但是不支持跟踪或计数数据。有关更多信息,请参见 collector (1) 手册页。

当连接到进程时,会使用运行 collect -P 的用户的 umask 创建目录,但是会以运行所连接进程的用户身份写入实验。如果执行连接的用户是超级用户,但 umask 不为零,则实验将失败。

-n

模拟运行:不运行目标,但输出要运行的实验的所有详细信息。打开 -v

-R

已过时。将针对该效果输出一条消息并退出。在以后的发行版中将删除此选项。

-V

输出当前版本。不再检查任何参数,也不执行进一步的处理。

-v

输出当前版本和正在运行的实验的更多详细信息。

-x

在从 exec 系统调用退出时使目标进程停止,以便允许调试器连接到目标进程。collect 命令将输出一条含有进程 PID 的消息。

要在 collect 停止调试器之后将其添加到目标,您可以按照下文中的过程进行操作。

  • collect -x 命令输出的消息获取进程的 PID。

  • 启动调试器

  • 将调试器配置为忽略 SIGPROF;如果您选择收集硬件计数器数据,则配置为忽略 Solaris 上的 SIGEMT 或 Linux 上的 SIGIO

  • 使用 dbxattach 命令连接到进程。

  • 为您要收集的实验设置收集器参数

  • 发出 collector enable 命令。

  • 发出 cont 命令以允许目标进程运行

由于进程在调试器的控制之下运行,因此收集器会记录一个实验。

或者,您可以连接到进程并使用 collect -P PID 命令收集实验。

跟踪子孙进程

跟踪子孙进程

始终会收集 collect 产生的初始进程(称为创始进程)中的数据。进程可以通过调用系统库函数(包括 forkexecsystemetc 的变量)来创建子孙进程。如果使用 -F 参数,收集器可以收集子孙进程的数据,并在父实验中针对每个子孙进程打开一个新实验。这些新实验是沿袭命名的,如下所示:

  • 将下划线附加到创建者的实验名称。

  • 将添加一个代码字母:"f" 表示 fork 或 "x" 表示其他子孙进程(包括 exec)。在 Linux 上,使用 "C" 表示 clone(2) 生成的子孙。

  • 在代码字母后面添加一个数字,它是子孙的索引。

  • 在沿袭项上附加实验后缀 ".er"。

例如,如果初始进程的实验名称为 "test.1.er",则其第三个派生创建的子孙进程的实验为 "test.1.er/_f3.er"。如果该子孙进程针对新映像执行 exec 操作,则相应的实验名称为 "test.1.er/_f3_x1.er"。

如果使用缺省值 -F on,则会跟踪由对 fork (2) 、 fork1 (2) 、 fork (3F) 、 vfork (2) 和 exec (2) 及其变体的调用所启动的子孙进程。对 vfork 的调用已在内部被替换为对 fork1 的调用。另外还跟踪由对 system (3C) 、 system (3F) 、 sh (3F) 、 popen (3C) 和类似函数及其相关子孙进程的调用所创建的子孙进程。在 Linux 上,缺省情况下会跟踪不带 CLONE_VM 标志的 clone() 所创建的子孙;使用 CLONE_VM 标志创建的子孙被视为线程而不是进程,因此会始终跟踪,这与 -F 设置无关。

如果使用 -F =<regex> 参数,则会跟踪名称与正则表达式匹配的所有子孙。匹配名称时,仅使用可执行文件的基名而不是完整路径或任何参数。

例如,要针对创始进程中第一个 system 调用的第一个 fork 的第一个 exec 的子孙进程捕获数据,请使用:

collect -F '=_x1_f1_x1'

要捕获 exec 而不是 fork 的所有变量的数据,请使用:

collect -F '=.*_x[0-9]/*'

要捕获 system("echo hello")(而非 system("goodbye"))调用的数据,请使用:

collect -F '=echo hello'

读取创始实验时,分析器和 er_print 会自动读取子孙进程的实验,并选择子孙进程的实验用于数据显示。

要从命令行专门选择要显示的数据,请将路径名显式指定为 er_print 或分析器。所指定的路径必须包含创始实验的名称以及创始目录中子孙实验的名称。

例如,要查看 test.1.er 实验的第三个派生的数据:

er_print test.1.er/_f3.er
analyzer test.1.er/_f3.er

您可以使用感兴趣的子孙实验的显式名称来准备实验组文件。

要在分析器中检查子孙进程,请装入创始实验并选择 "View"(查看)> "Filter data"(过滤数据)。分析器将显示一个实验列表,其中只选中了创始实验。取消选中创始实验并选中感兴趣的子孙实验。

分析脚本

分析脚本

缺省情况下,collect 不再要求其目标是 ELF 可执行文件。如果在脚本中调用 collect,将针对为执行脚本而启动的程序以及所有子孙进程收集数据。要仅针对特定进程收集数据,请使用 -F 标志指定要跟踪的可执行文件的名称。

例如,要分析脚本 foo.sh,但是首先从可执行文件 bar 收集数据,需要使用命令:

collect -F =bar foo.sh

将针对为执行脚本而启动的创始进程和从脚本产生的所有 bar 进程收集数据,但不针对其他进程收集数据。

Java 分析

Java 分析

Java 分析包括在 JVM 虚拟机运行 .class 或 .jar 文件时收集它的性能实验。如果可能,将在 Java 模型和计算机模型中收集调用堆栈。

可以将查看模式设置为 "User"(用户)、"Expert"(专家)或 "Machine"(计算机)来显示数据。"User"(用户)模式按名称显示每个方法,将已解释的方法和 HotSpot 编译的方法的数据聚集在一起;它还抑制非用户 Java 线程的数据。"Expert"(专家)模式将 HotSpot 编译的方法与已解释的方法分开,且不抑制非用户 Java 线程。"Machine"(计算机)模式在进行解释时根据 JVM 计算机显示已解释的 Java 方法的数据,并对指定的方法报告使用 Java HotSpot 虚拟机编译的方法的数据。显示所有线程。在所有三种模式下,对于 Java 目标调用的任何非 OpenMP、C、C++ 或 Fortran 代码,都以通用的方法报告数据。这类代码与 Java 本机方法相对应。分析器和 er_print 实用程序可以在 "User"(用户)、"Expert"(专家)和 "Machine"(计算机)查看模式之间切换,缺省设置为 "User"(用户)。

支持基于时钟的分析和硬件计数器溢出分析。同步跟踪仅针对 Java 监视器调用以及本机代码中的同步调用收集数据,而不会收集 JVM 中内部同步调用的相关数据。

Java 不支持堆跟踪,在指定堆跟踪时会生成错误。

某些 Java 代码的 jar 文件中包含共享对象。在应用程序运行时会将共享对象提取到临时目录,而在应用程序终止时将删除共享对象。共享对象名称将记录在实验映射文件中,而 jar 文件名不会。要读取此类实验,请确保在 <tt>.er.rc</tt> 文件中添加列出 jar 文件的 <tt>addpath</tt> 指令,或者从分析器 GUI 添加路径,或者在 <tt>er_print</tt> 中使用 <tt>addpath</tt> 命令。如果归档实验时 <tt>.er.rc</tt> 文件中存在 <tt>addpath</tt> 指令,则归档共享对象。

collectjava 的目标名称插入参数列表时,它会按照先 JDK_HOME 再 JAVA_PATH 的顺序检查 java 目标路径的环境变量。对于设置的第一个环境变量,生成的目标会被验证为 ELF 可执行文件。否则,collect 将会失败并显示错误来说明使用的环境变量以及尝试的完整路径名称。

如果这些环境变量均未设置,collect 命令将使用您的 PATH 设置的版本。如果您的 PATH 中没有 java,则会尝试 /usr/java/bin/java 系统缺省值。

使用 dlopen 的 Java 分析

使用 dlopen 的 Java 分析

有些应用程序不是纯的 Java,而是 C 或 C++ 应用程序,这些应用程序会调用 dlopen 以装入 libjvm.so,然后通过调用 JVM 来启动 JVM。收集器会设置一个环境变量,以便 Java 分析会自动启用。

共享对象处理

共享对象处理

通常,collect 命令会为目标地址空间中的所有共享对象收集数据,而不管这些对象是在初始库列表中,还是使用 dlopen 显式装入。但是,在有些情况下不会分析某些共享对象。

当使用延迟装入调用目标程序时就会发生这种情况。在这种情况下,库不是在启动时装入的,并且不是通过显式调用 dlopen 装入的,因此共享对象名称不包括在实验中,其中的所有 PC 将映射到 <Unknown> 函数。解决方法是设置 LD_BIND_NOW,以强制在启动时装入库。

当使用 -B direct 链接选项生成可执行文件时也会发生这种情况。在这种情况下,通过专门针对 dlopen 动态链接程序入口点的调用来动态装入对象,并且忽略 libcollector 插入。共享对象名称不包括在实验中,其中的所有 PC 将映射到 <Unknown> 函数。解决方法是不使用 -B direct

数据收集和信号

数据收集和信号

分析信号

信号可用于时钟分析和硬件计数器溢出分析。SIGPROF 用于所有实验的数据收集。生成信号的周期取决于收集的数据。SIGEMT (Solaris) 或 SIGIO (Linux) 用于硬件计数器溢出分析。溢出间隔取决于要分析的用户参数。任何使用或处理分析信号的用户代码都可能会干扰数据收集。当收集器安装用于分析信号的信号处理程序时,它会设置一个标志来确保系统调用不被中断以传送信号。此设置可能会更改将分析信号用于其他用途的目标程序的行为。

当收集器安装用于分析信号的信号处理程序时,它会记住目标是否已安装其自己的信号处理程序。收集器还会插入到某些信号处理例程且不允许用户为这些信号安装信号处理程序;它会保存用户的处理程序,就像收集器在启动实验时替换用户处理程序一样。

分析信号由内核中的分析计时器或硬件计数器溢出处理代码提供,或用于响应以下各项: kill (2) 、 sigsend (2) 、 tkill (2) 、tgkill(2) 或 _lwp_kill (2) 系统调用; raise (3C) 或 sigqueue (3C) 库调用;或 kill (1) 命令。会随信号提供信号代码,以便收集器能区分源。如果针对分析提供,收集器会处理该代码;如果不是针对分析提供,则会将其提供给目标信号处理程序。

dbx 下运行收集器时,提供的分析信号的信号代码有时会被损坏,此时会当作分析信号是从系统或库调用或某个命令生成的。在这种情况下,会错误地将其提供给用户的处理程序。如果用户处理程序设置为 SIG_DFL,将导致进程的信息转储失败。

在连接到目标进程后调用收集器时,收集器会安装其信号处理程序,但它无法插入到信号处理例程。如果用户代码在连接后安装信号处理程序,则该处理程序会覆盖收集器的信号处理程序,且数据将会丢失。

请注意,任何信号(包括任一分析信号)都可能导致系统调用的提早终止,程序必须做好准备处理该行为。当 libcollector 安装信号处理程序以用于数据收集时,它指定重新启动那些可重新启动的系统调用,但是一些系统调用(例如 sleep (3C) )将提早返回,并且不报告错误。

抽样信号和暂停-恢复信号

用户可以将信号指定为抽样信号 (-l) 或暂停-恢复信号 (-y)。建议将 SIGUSR1 或 SIGUSR2 用于此用途,但也可以使用目标未使用的任何信号。

如果进程未将分析信号用于其他用途,则可以使用这些信号,但仅在没有其他信号可用时才能使用这些信号。收集器会插入到某些信号处理例程且不允许用户为这些信号安装信号处理程序;它会保存用户的处理程序,就像收集器在启动实验时替换用户处理程序一样。

如果在连接到目标进程后调用收集器,且用户代码为抽样信号或暂停-恢复信号安装了一个信号处理程序,则这些信号将无法再按指定完成操作。

OpenMP 分析

OpenMP 分析

OpenMP 程序的数据收集会收集可使用三种查看模式中的任意一种模式显示的数据,就像 Java 程序的数据收集一样。在用户模式下,从线程按实际从主线程克隆的方式显示,并使其调用堆栈匹配主线程的调用堆栈。调用堆栈中来自 OpenMP 运行时代码 (libmtsk.so) 的帧会被抑制。在专家用户模式下,主从线程的显示方式不同,编译器生成的显式函数可见,来自 OpenMP 运行时代码 (libmtsk.so) 的帧会被抑制。对于计算机模式,将显示实际的本机堆栈。

在用户模式下,每当运行时库处于多种状态之一时,便会引入多种人工函数作为调用堆栈的叶函数。这些函数包括 <OMP-overhead>、<OMP-idle>、<OMP-reduction>、<OMP-implicit_barrier>、<OMP-explicit_barrier>、<OMP-lock_wait>、<OMP-critical_section_wait> 和 <OMP-ordered_section_wait>。

在时钟分析实验的数据中添加了另外三个时钟分析度量:

 
OpenMP Work (ompwork)
OpenMP Wait (ompwait)
Master Thread Time (masterthread)

当 OpenMP 运行时认为代码在执行工作时,"OpenMP Work"(OpenMP 工作)就会计数。它包括进程消耗用户 CPU 时间的时间,但还包括进程消耗系统 CPU 时间、等待页面失败、等待 CPU 等的时间。因此,"OpenMP Work"(OpenMP 工作)可能会超过用户 CPU 时间。当 OpenMP 运行时认为进程在等待时,"OpenMP Wait"(OpenMP 等待)就会累积。"OpenMP Wait"(OpenMP 等待)可以包括忙等待(旋转等待)的用户 CPU 时间,但也包括休眠等待的其他等待时间。

"Master Thread Time"(主线程时间)是主线程消耗的总时间。只能在 Solaris 实验中查看该时间。该时间与系统时钟时间相对应。

在缺省情况下,非独占度量可见,而独占度量不可见。这两个度量的总和等于 "Total Thread Time"(总线程时间)度量。将在所有时钟分析实验和硬件计数器溢出分析实验中添加这两个度量。

针对程序执行期间的每个平行区域条目收集信息可能代价很高。可以通过设置 SP_COLLECTOR_NO_OMP 环境变量来压低开销。如果您设置 SP_COLLECTOR_NO_OMP,程序执行时间将显著缩短,但是将看不到自从属线程向上传播到调用方并最终传播到 main() 的数据,而在未设置该变量时将能看到这些数据。

缺省情况下,会在此版本中为 OpenMP 3.0 启用一个新的收集器。它可以分析使用显式任务的程序。只有在修补版本的 libmtsk.so 可用时,才可以使用该新收集器分析使用早期的编译器生成的程序。如果尚未安装,可以通过设置 SP_COLLECTOR_OLDOMP 环境变量来将数据收集切换至使用旧收集器。

请注意,OpenMP 分析功能仅适用于使用 Oracle Solaris Studio 编译器编译的应用程序,因为它取决于 Oracle Solaris Studio 编译器运行时。使用 GNU 编译的代码仅会看到计算机级别的调用堆栈。

内存空间分析和数据空间分析

内存空间分析和数据空间分析

在内存空间分析中,将针对计算机的物理结构(例如,高速缓存行、内存区或页面)报告内存相关事件(例如,高速缓存未命中次数)。

在数据空间分析中,将针对导致事件的数据结构引用而非仅针对发生内存相关事件的指令报告内存相关事件。数据空间分析仅在运行 Oracle Solaris 的 SPARC 系统上可用。它在运行 Oracle Solaris 或 Linux 的 x86 系统上尚不可用。

对于内存空间或数据空间分析,收集的数据必须是使用基于内存的计数器的硬件计数器分析。对于 SPARC 平台或 x86 Oracle Solaris 平台上的精确计数器,缺省情况下将收集内存空间/数据空间数据。

为了支持数据库空间分析,应使用 -xhwcprof 标志编译可执行文件。此标志适用于使用 C、C++ 和 Fortran 编译器进行编译,但仅在 SPARC[R] 平台上有意义。在其他平台上将忽略该标志。如果不使用 -xhwcprof 编译可执行文件,er_print 中的 data_layoutdata_singledata_objects 命令将不显示数据。数据空间分析无需针对精确计数器使用 -xhwcprof

在具有精确中断的计算机上,内存空间分析不需要使用 -xhwcprof 标志进行编译。数据空间分析(即使在此类计算机上)不需要标志。

对于收集的数据,er_print 实用程序允许执行三条附加命令(data_objectsdata_singledata_layout)以及与内存对象相关的多个命令。有关更多信息,请参见 er_print(1) 手册页。

此外,性能分析器包括两个与数据空间分析有关的数据视图(标签为 "DataObjects"(数据对象)和 "DataLayout"(数据布局))以及一组与内存对象相关的视图。

MPI 分析

MPI 分析

collect 命令可用于 MPI 分析,以管理成员 MPI 进程的数据收集、收集 MPI 跟踪数据,以及使用每个 MPI 进程的“子实验”将数据组织为单个“创始”实验。

只需在所需的 collect 命令及其参数(假定您已插入 -- 参数以指示 mpirun 参数的结尾)前加上启动 MPI 作业及其参数的命令,即可将 collect 命令与 MPI 配合使用。例如,在 SMP 计算机上,

% mpirun -np 16 -- a.out 3 5

可替换为

% collect -M OMPT mpirun -np 16 -- a.out 3 5

该命令会在 16 个 MPI 进程中的每个进程上运行一个 MPI 跟踪实验,将它们都收集到一个 MPI 实验中(以命名实验的常用约定进行命名)。它假定使用 MPI 的 Oracle Message Passing Toolkit(以前称为 Sun HPC ClusterTools)版本。

初始 collect 进程会重设 mpirun 命令的格式,来指定对各个 MPI 进程运行 collect 命令(带有适当的参数)。

请注意,目标名称前面的 -- 参数对于 MPI 分析而言是必需的(虽然它对于 mpirun 本身而言是可选的),以便 collect 可以将 mpirun 参数与目标及其参数分隔开来。如果未提供 -- 参数,collect 将输出一条错误消息且不会运行实验。

此外,collect 会将 -x PATH 参数添加到 mpirun 参数中,以便远程收集能够找到其目标。 如果您环境中的任何环境变量以 "VT_" 或 "SP_COLLECTOR_" 开头,则会对每个变量使用 -x 标志来将其传递至远程收集。

支持运行 MIMD MPI,且同样要求在每个 ":" 之后添加 "--" 参数(为其指示新目标和本地 mpirun 参数)。如果未提供 -- 参数,collect 将输出一条错误消息且不会运行实验。

某些版本的 Oracle Message Passing Toolkit 或 Sun HPC ClusterTools 具有进行 MPI 状态分析的功能。在使用这种版本的 MPI 运行的 MPI 实验上收集时钟分析数据时,可能会显示两个其他度量:

 
MPI Work (mpiwork)
MPI Wait (mpiwwait)

"MPI Work"(MPI 工作):这种度量将在进程正在 MPI 运行时内执行工作(如处理请求或消息)时进行累积;"MPI Wait"(MPI 等待):这种度量将在进程正在 MPI 运行时内等待事件、缓冲区或消息时进行累积。

在 Solaris 系统上,"MPI Wait"(MPI 等待)将在 MPI 库在等待期间休眠或旋转时进行累积。在 Linux 系统上,"MPI Wait"(MPI 等待)将在 MPI 库在等待期间旋转时进行累积;如果 MPI 库在等待期间休眠(产生 CPU)则不会进行累积,并且会根据实际等待时间减去这部分时间。

在分析器中,当收集 MPI 跟踪数据时,会显示两个其他标签:"MPI Timeline"(MPI 时间线)和 "MPI Chart"(MPI 图表)。

不再支持使用 mpirun 在 MPI 进程上产生显式 collect 命令的方法来收集 MPI 跟踪数据,因此不应使用该方法。该方法仍可用于所有其他类型的数据。

MPI 分析基于开源 VampirTrace 5.5.3 版本。它可识别多个 VampirTrace 环境变量以及新的环境变量 VT_STACKS,该环境变量控制调用堆栈是否记录在数据中。有关这些变量的含义的详细信息,请参见 VampirTrace 5.5.3 文档。

环境变量 VT_BUFFER_SIZE 的缺省值将 MPI API 跟踪收集器的内部缓冲区限制为 64 MB,而环境变量 VT_MAX_FLUSHES 的缺省值将缓冲区的刷新次数限制为 1。在达到限制之后,不会再将要记录的事件写入跟踪文件。这些环境变量适用于并行应用程序的每个进程,也就是说包含 n 个进程的应用程序通常会创建大小是串列应用程序 n 倍的跟踪文件。

要去掉限制并获取应用程序的完整跟踪,请将 VT_MAX_FLUSHES 设置为 0。该设置将导致 MPI API 跟踪收集器在缓冲区已满时刷新磁盘的缓冲区。要更改缓冲区大小,请使用环境变量 VT_BUFFER_SIZE。该变量的最佳值取决于要跟踪的应用程序。设置较小的值将增加应用程序可以使用的内存,但是将触发 MPI API 跟踪收集器频繁进行缓冲区刷新。这些缓冲区刷新可能会显著改变应用程序的行为。另一方面,设置较大的值(如 2G)将可以使 MPI API 跟踪收集器刷新缓冲区的次数降至最低,但是将减少应用程序可以使用的内存。如果没有足够的内存可用来容纳缓冲区和应用程序数据,可能会造成应用程序的某些部分交换至磁盘,这也会导致应用程序的行为发生显著改变。

另一个重要的变量是 VT_VERBOSE,该变量会打开多个错误和状态消息;如果出现问题,建议将其设置为 2 或更大值。

通常,当 mpirun 目标存在时,MPI 跟踪输出数据是后处理的;将处理的数据文件写入实验,而将关于后处理时间的信息写入实验标题。如果显式禁用 MPI 跟踪,就不会执行 MPI 后处理。

后处理失败时,报告错误,且任何 MPI 标签或 MPI 跟踪度量将都不可用。

即使 mpirun 目标没有实际调用 MPI,仍然会记录实验,但不会生成任何 MPI 跟踪数据。该实验将报告 MPI 后处理错误,任何 MPI 标签或 MPI 跟踪度量都将不可用。

如果将环境变量 VT_UNIFY 设置为 "0",collect 不会运行后处理例程 er_vtunifyer_mpipp。首次在实验上调用 er_printanalyzer 时,将运行这些后处理例程。

将 collect 与 ppgsz 配合使用

将 collect 与 ppgsz 配合使用

通过针对 ppgsz 命令运行 collect 命令并指定 -F on 标志,可将 collect 命令与 ppgsz 命令配合使用。创始实验位于 ppgsz 可执行文件上,我们不需要关注它。如果您的路径找到 32 位版本的 ppgsz,并且实验在支持 64 位进程的系统上运行,则 collect 命令首先要做的是针对它的 64 位版本执行 exec 函数,创建 _x1.er。该可执行文件将进行派生,创建 _x1_f1.er。子孙进程会在您路径中的第一个目录中,针对指定目标尝试执行 exec 函数,然后在第二个目录中执行,直到其中一个 exec 函数成功运行。例如,如果第三个尝试成功,则前两个子孙实验分别命名为 _x1_f1_x1.er_x1_f1_x2.er,并且这两个实验都完全为空。目标上的实验是来自成功的 exec 的某个实验,在本例中为第三个实验,命名为 _x1_f1_x3.er 并存储在创始实验之下。通过针对 test.1.er/_x1_f1_x3.er 调用分析器或 er_print 实用程序,可以直接处理该实验。

如果 64 位 ppgsz 是运行的初始进程,或者如果在 32 位内核上调用 32 位 ppgsz,那么,针对实际目标执行 execfork 子孙的数据位于 _f1.er 中,而实际目标的实验位于 _f1_x3.er 中,前提是采用与上例相同的路径属性。

请参见上文的“跟踪子孙进程”部分。有关硬件计数器的更多信息,请参见下文的“硬件计数器溢出分析”部分。

针对 setuid/setgid 目标使用 collect

针对 setuid/setgid 目标使用 collect

collect 命令通过将一个共享库 libcollector.so 以及用于特定跟踪数据收集的其他共享库插入到目标的地址空间 (LD_PRELOAD) 中来进行操作。这些共享库用于编写构成实验的文件。

如果针对调用 setuid 或 setgid 的可执行文件或创建的子孙进程会调用 setuid 或 setgid 的可执行文件调用 collect,可能会发生多个问题。如果运行实验的用户不是超级用户,收集会因为共享库未安装在可信目录中而失败。解决方法是以 root 用户身份运行实验,或使用 crle (1) 授予权限。当然,在应对安全障碍时用户应格外小心,操作风险需自行承担。

此外,必须为运行 collect 命令的用户、由使用 exec 执行的程序的 setuid/setgid 属性设置的任何用户或组以及该程序自身设置的任何用户或组,将该用户的 umask 设置为允许写权限。如果未正确设置掩码,某些文件可能无法写入实验,并且可能无法处理实验。如果可以写入日志文件,用户尝试处理实验时将显示错误。

请注意,在作为一个用户连接到其他用户拥有的进程时,必须将 umask 设置为允许拥有该进程的用户写入。

如果目标本身发出了设置 UID 或 GID 的任何系统调用,或者如果目标更改其 umask,然后对其他某个进程派生或运行 exec,或者 crle 用于配置运行时链接程序如何搜索共享对象,则可能会出现其他问题。

如果在更改其有效 GID 的目标上以超级用户身份启动实验,实验终止时自动运行的 er_archive 进程将失败,原因是它需要未标记为可信的共享库。在这种情况下,您可以在实验终止后立即在记录实验的计算机上显式手动运行 er_archive(或 er_print 或分析器)。

收集的数据

收集的数据

会收集三种类型的数据:分析数据、跟踪数据和抽样数据。分析和跟踪中记录的数据包中包括每个 LWP 的调用堆栈、LWP、线程和 CPU ID 以及某些事件特定的数据。抽样中记录的数据包中包含执行统计信息等全局数据,但不包含程序特定或事件特定的数据。所有数据包都包括时间戳。

每种数据类型说明了该数据派生的度量,既是名称也是用户在运行实验时会在 metrics 命令中使用的字符串。

基于时钟进行分析

基于时钟的分析中记录的事件特定数据是每个计数微状态的计数数组。微状态数组由系统按指定频率增加,且在处理分析信号时由收集器记录。

基于时钟的分析可按多种频率运行,这些频率必须是用于分析计时器的时钟精度的倍数。如果您尝试在安装的操作系统不支持高精度分析的计算机上执行高精度分析,该命令会输出一条警告消息,并且使用支持的最高精度。同样,不是系统支持的精度倍数的定制设置也将向下舍入到该精度最接近的非零倍数,且会输出一条警告消息。

基于时钟的分析数据会转换为以下度量:

 
Total Thread Time (total)
Total CPU Time (totalcpu)
User CPU Time (user)
System CPU Time (system)
Trap CPU Time (trap)
User Lock Time (lock)
Data Page Fault Time (datapfault)
Text Page Fault Time (textpfault)
Kernel Page Fault Time (kernelpfault)
Stopped Time (stop)
Wait CPU Time (wait)
Sleep Time (sleep)

对于多线程应用程序上的实验,将加总进程中所有线程的所有时间。"Total Thread Time"(总线程时间)会加总实际经过的时间,并乘以进程中的平均线程数量。

如果对 OpenMP 程序执行基于时钟的分析,将提供以下三种其他度量:

 
OpenMP Work (ompwork)
OpenMP Wait (ompwait)
Master Thread Time (masterthread)

在 Solaris 上,以并行方式执行工作时,"OpenMP Work"(OpenMP 工作)会累积。在以下情况下“OpenMP 等待”会累积:OpenMP 运行时正在等待进行同步时、该等待正在使用 CPU 时间或正在休眠时,以及正在以并行方式执行工作,但未在 CPU 上安排线程时。"Master Thread Time"(主线程时间)仅代表主线程中的时间。

在 Linux 上,仅当进程在用户模式或系统模式下处于活动状态时,"OpenMP Work"(OpenMP 工作)和 "OpenMP Wait"(OpenMP 等待)才会累积。除非您已指定 OpenMP 应执行忙等待,否则,Linux 上的“OpenMP 等待”将没有用处。在 Linux 上不会提供 "Master Thread Time"(主线程时间)。

如果对 MPI 程序(在 Oracle Message Passing Toolkit 或 Sun HPC ClusterTools 8.1 或更高版本中运行)执行基于时钟的分析,将提供以下两种其他度量:

 
MPI Work (mpiwork)
MPI Wait (mpiwait)

在 Solaris 上,在 MPI 运行时处于活动状态时,"MPI Work"(MPI 工作)会累积。在以下情况下,"MPI Wait"(MPI 等待)会累积:MPI 运行时正在等待发送或接收消息;或 MPI 运行时处于活动状态,但线程未在 CPU 上运行。

在 Linux 上,仅当进程在用户模式或系统模式下处于活动状态时,“MPI 工作”和“MPI 等待”才会累积。除非您已指定 MPI 应执行忙等待,否则,Linux 上的“MPI 等待”将没有用处。

硬件计数器溢出分析

硬件计数器溢出分析会记录在处理溢出信号时硬件计数器计数的事件数量。

可用的计数器取决于特定处理器芯片和操作系统。运行不带任何其他参数的 collect -h 命令将列出处理器、可用的硬件计数器数量、所有计数器的列表以及该处理器的缺省硬件计数器集。别名为通用名称的计数器将首先显示在列表中,然后是原始硬件计数器列表。在输出已知计数器的列表之后,会输出芯片的参考手册名称以及为该芯片定义的缺省计数器集。

如果性能计数器子系统和 collect 都不知道特定芯片上的计数器名称,这些表将为空。尽管如此,在大多数情况下,可以用数值指定计数器。输出行的格式如下所示:

可用于分析的有别名硬件计数器:

 
cycles[/{0|1}],<interval> ('CPU Cycles', alias for Cycle_cnt; CPU-cycles)
insts[/{0|1}],<interval> ('Instructions Executed', alias for Instr_cnt; events)
dcrm[/1],<interval> ('D$ Read Misses', alias for DC_rd_miss; load events)
...

可用于分析的原始硬件计数器:

 
Cycle_cnt[/{0|1}],<interval> (CPU-cycles)
Instr_cnt[/{0|1}],<interval> (events)
DC_rd[/0],<interval> (load events)
SI_snoop[/0],<interval> (not-program-related events)
...

在有别名的计数器输出的第一行中,第一个字段 "cycles" 提供可以在 -h 参数中使用的计数器名称。后面指定了可用于该计数器的寄存器。度量名称为 "CPU Cycles"(CPU 周期),原始硬件计数器名称为 "Cycle_cnt"。最后一个字段 "CPU-cycles" 指定计数的单位类型。类型信息最多可以包含两个词。类型信息的第二个词或唯一词可以是 "CPU-cycles" 或 "events"。如果计数器可用于提供基于时间的度量,则该值为 CPU-cycles;否则该值为 events。

在上述有别名的计数器输出的第二个输出行中,行末为 "events" 而不是 "CPU-cycles",表示它用于计数事件而无法转换为时间。

上述第三个输出行的行末包含由两个词组成的类型信息 "load events"。类型信息的第一个词的值可以是 "load"、"store"、"load-store" 或 "not-program-related"。上述前三个类型值指示计数器与内存相关,因此,在用于 collect -h 命令时,计数器名称可以前置 "+" 符号。"+" 符号表示数据收集请求尝试查找导致溢出计数器事件的精确指令和虚拟地址。

在一些芯片上,计数器中断是精确的,不需要 "+" 号。此类计数器在事件类型后面用字 "(precise)" 表示。

"not-program-related" 值表示计数器会捕获由其他某个程序启动的事件,例如 CPU 到 CPU 的高速缓存嗅探。使用计数器进行分析时将生成警告,并且分析不记录调用堆栈。但是,它会显示名为 "collector_not_program_related" 的人工函数所使用的时间。线程 ID 和 LWP ID 会被记录,但没有任何意义。

原始硬件计数器列表中的每行包括由 cputrack (1) 使用的内部计数器名称、可以在其上使用计数器的寄存器编号、缺省溢出值和计数器单位(可以是 CPU-cycles 或 events)。

硬件计数器数据报告的度量根据使用的计数器命名。如果计数器按周期测量,则数据将转换为时间;如果它按事件测量,则数据将报告为事件计数。一个用户选项还允许基于周期的计数器显示为事件。

如果收集两个特定的计数器 "cycles" 和 "insts",则可以使用两个额外的度量,即 "CPI" 和 "IPC",分别表示每指令周期数和每周期指令数。它们始终以比率(而非时间、计数或百分比)的形式显示。高 CPI 值或低 IPC 值指示代码在计算机中运行效率低;相反,低 CPI 值或高 IPC 值指示代码在管道中运行效率高。

示例

示例 1:使用上述样例输出中列出的有别名计数器信息,以下命令:

collect -h cycles,3600003

启用 "CPU Cycles"(CPU 周期)分析,使用所选的 3600003 在 3.6 GHz 系统上每个线程每秒生成大约 1000 个事件的峰值事件率。(请注意,生成过高的事件率最终将影响您尝试分析的性能。在 Solaris 系统上,您可以使用 on/high/low,而不是数值溢出间隔。)

示例 2:

在 AMD Opteron 计算机上运行不带任何其他参数的 collect -h 命令将生成如下所示的原始硬件计数器输出:

 
FP_dispatched_fpu_ops[/{0|1|2|3}],<interval> (events)
FP_cycles_no_fpu_ops_retired[/{0|1|2|3}],<interval> (CPU-cycles)
...

使用上述原始硬件计数器输出,以下命令:

collect -h FP_dispatched_fpu_ops~umask=0x3/2,10007

允许以每 10007 次事件捕获 1 次的速率跟踪浮点加法和乘法运算。(有关有效属性值的详细信息,请参阅处理器文档)。值 "/2" 指定使用硬件的寄存器 2 捕获数据。

支持的 Solaris 系统及支持的 Linux 版本(运行 2.6.32 版或更高版 Linux 内核)已安装针对硬件计数器溢出分析的必要操作系统支持。

运行 2.6.32 版之前内核的受支持 Linux 系统使用 perfctr 框架;您需要在系统上安装所需的 perfctr 修补程序。通过在 Web 上搜索“perfctr 修补程序”可以找到此修补程序。安装说明包含在修补程序下载位置的 tar 文件中。收集器使用 LD_LIBRARY_PATH 搜索用户级 libperfctr.so 库,然后在 /usr/local/lib/usr/lib//lib/ 中进行搜索(对于 32 位版本);或者在 /usr/local/lib64 /usr/lib64//lib64/ 中进行搜索(对于 64 位版本)。

同步延迟跟踪

同步延迟跟踪会记录对调用中的实时延迟超过指定阈值的多个线程同步例程的所有调用。数据包中包含进入和退出同步例程的时间戳、线程 ID 以及启动请求时的 LWP ID。(来自线程的同步请求可以在一个 LWP 上启动,而在另一个 LWP 上完成。)

同步延迟跟踪数据会转换为以下度量:

 
Synchronization Wait Time (sync)
Synchronization Delay Events (syncn)
堆跟踪

堆跟踪会记录对 mallocfreereallocmemalignvalloc 的所有调用以及请求的块大小、块地址及 realloc 的之前地址。将在 Oracle Solaris 上记录对 calloc 的调用,但是在 Linux 上不记录。

堆跟踪数据会转换为以下度量:

 
Allocations (heapalloccnt)
Bytes Allocated (heapallocbytes)
Leaks (heapleakcnt)
Bytes Leaked (heapleakbytes)

泄漏是指未释放的分配。如果分配了零长块,将计数为分配了零字节的分配。如果未释放零长块,将计数为泄露了零字节的泄露。

堆跟踪实验可能很大,因此处理速度可能很慢。

IO 跟踪

IO 跟踪会记录对标准 IO 例程的所有调用和所有 IO 系统调用。

IO 跟踪数据会转换为以下度量:

 
Bytes Read (ioreadbytes)
Read Count (ioreadcnt)
Read Time (ioreadtime)
Bytes Written (iowritebytes)
Write Count (iowritecnt)
Write Time (iowritetime)
Other IO Count (ioothrcnt)
Other IO Time (ioothertime)
IO Error Count (ioerrornt)
IO Error Time (ioerrortime)
MPI 跟踪

MPI 跟踪会记录针对需要大量时间才能完成的函数对 MPI 库的调用。MPI 跟踪使用开源 VampirTrace 代码实施。

MPI 跟踪数据会转换为以下度量:

 
MPI Time (mpitime)
MPI Sends (mpisendcnt)
MPI Bytes Sent (mpisendbytes)
MPI Receives (mpirecvcnt)
MPI Bytes Received (mpirecvbytes)
Other MPI Events (mpiothercnt)

MPI 时间是 MPI 函数中所用的总线程时间。如果还收集了 MPI 状态时间,则除 MPI_Init 和 MPI_Finalize 之外的所有 MPI 函数的 MPI 工作时间加上 MPI 等待时间应大约等于 MPI 工作时间。在 Linux 上,MPI 等待和 MPI 工作基于用户 CPU 时间加系统 CPU 时间,而 MPI 时间基于实际时间,所以这些数值将不匹配。

"MPI Bytes Received"(接收的 MPI 字节数)度量会计算所有消息中接收的实际字节数。"MPI Bytes Sent"(发送的 MPI 字节数)会计算所有消息中发送的实际字节数。“MPI 发送数”会计算发送的消息数,“MPI 接收数”会计算接收的消息数。MPI_Sendrecv 同时作为发送和接收进行计数。"Other MPI Events"(其他 MPI 事件)会对跟踪中既不是发送也不是接收的事件进行计数。

计数数据

计数数据通过检测可执行文件以及计数执行的每个指令的次数进行记录。它还会对函数中第一条指令的执行次数进行计数,并调用该函数执行计数。(仅限 SPARC 系统)它还会对分支延迟槽中指令的取消次数进行计数。

计数数据会转换为以下度量:

 
Bit Func Count (bit_fcount)
Bit Inst Exec (bit_instx)
Bit Inst Annul (bit_annul) -- SPARC only
数据争用检测数据

数据争用检测数据包含构成竞争的成对争用访问事件。这些事件会合并为一个争用,而两个访问的调用堆栈相同的争用会合并为一个争用组。

数据争用检测数据将转换为以下度量:

 
Race Accesses (raccess)
死锁检测数据

死锁检测数据包含锁定冲突的成对线程。

死锁检测数据会转换为以下度量:

 
Deadlocks (deadlocks)
抽样和全局数据

抽样是指沿着执行时间线生成标记的过程。在每个抽样点,都会记录执行统计信息。在抽样点记录的所有数据对程序来说都是全局的,且不会映射到函数级度量。

在进程开始和终止时始终会抽样。缺省情况下,或指定了非零 -S 参数时,会按指定间隔定期抽样。此外,也可使用 libcollector(3) API 进行抽样。

在每个抽样点记录的数据都包含来自内核的微状态计数信息,以及内核中保留的多种其他统计信息。

限制

限制

大多数性能分析器二进制文件都需要从包含这些文件的安装中查找共享库。用户不得将 LD_LIBRARY_PATH 设置为包括其他工具安装的任何库目录。如果将 LD_LIBRARY_PATH 设置为其他安装,这些二进制文件可能无法执行。

收集器最多可支持 32,000 个用户线程。其他线程中的数据将被放弃,并生成收集器错误。要支持更多线程,请将 SP_COLLECTOR_NUMTHREADS 环境变量设置为更大的数字。

缺省情况下,收集器会收集 256 帧深度的堆栈。要支持较深的堆栈,请将 SP_COLLECTOR_STACKBUFSZ 环境变量设置为更大的数字。

收集器会插入到某些信号处理例程中,以保护其针对基于时钟的分析的 SIGPROF 信号使用和针对硬件计数器溢出分析的 SIGEMT (Solaris) 或 SIGIO (Linux) 使用,使其免受目标程序中断。请参见上文的“数据收集和信号”部分。

收集器会插入 setitimer (2) 中,确保在启用基于时钟的分析时目标程序无法使用分析计时器。

收集器会插入硬件计数器库 libcpc.so 中的函数,确保在收集器收集性能数据时应用程序无法使用硬件计数器。插入的函数会返回值 -1。

数据空间分析不适用于运行 Linux 操作系统的系统或运行 Solaris 操作系统的 x86 系统。

在此版本中,用于收集定期抽样的数据在运行 Linux 操作系统的系统上不可靠。

在此版本中,当在运行 RedHat Enterprise Linux 操作系统的系统上分析多线程应用程序时,发现了较大数据差异。

在运行 cpustat 的系统上无法运行硬件计数器溢出分析,因为 cpustat 会控制计数器而不让用户进程使用它们。

Java 分析需要 Java[TM] 2 SDK (JDK) 7 Update 11 或更高版本的 JDK 7。

collect 无法用于使用 -xprofile=tcov 标志编译的可执行文件。

对于所创建的使用 setuid 属性的子孙进程,或者通过针对未动态链接的可执行文件调用 exec 来创建的任何子孙进程,不会收集其数据。此外,后续子孙进程可能会生成损坏或无法读取的实验。解决方法是确保生成的所有进程都是动态链接的且没有 setuid 属性。

调用 vfork (2) 的应用程序通过调用 fork1 (2) 来替换这些调用。

无法在 Linux 5 系统上收集计数数据 (collect -c);根本无法在任何 Linux 系统上收集 32 位二进制文件的计数数据。

See also

analyzer (1) 、 collector (1) 、 dbx (1) 、 er_archive (1) 、 er_cp (1) 、 er_export (1) 、 er_mv (1) 、 er_print (1) 、 er_rm (1) 、 tha (1) 、 libcollector (3)

性能分析器手册