Oracle Solaris Studio 12.2:性能分析器

第 3 章 收集性能数据

性能分析的第一个阶段是数据收集。本章介绍了进行数据收集的要求、数据的存储位置、如何收集数据以及如何管理数据收集。有关数据本身的更多信息,请参见第 2 章

从内核收集数据需要单独的工具 er_kernel。有关更多信息,请参见第 9 章

本章包含以下主题。

编译和链接程序

无论程序使用何种编译器选项进行编译,您都可以为该程序收集和分析数据,但有些选项会影响能够在性能分析器中收集或查看的内容。以下几个小节介绍了在编译和链接程序时应考虑的问题。

源代码信息

查看带注释的“源代码”和“反汇编”分析中的源代码以及“行”分析中的源代码行,就必须使用 -g 编译器选项(对于 C++ 来说为用于启用前端内联的 -g0)编译感兴趣的源文件,以生成调试符号信息。调试符号信息的格式可以是 DWARF2 或 stabs,由 -xdebugformat=(dwarf|stabs) 指定。缺省的调试格式是 dwarf

要准备带有调试信息的编译对象来允许数据空间分析(当前仅适用于 SPARC 处理器),请通过指定 -xhwcprof 和任何级别的优化来进行编译。(目前,这种功能在未经过优化的情况下无法使用。要查看“数据对象”分析中的程序数据对象,也要添加 -g(对于 C++ 来说为 -g0)以获取全部符号信息。

用 DWARF 格式的调试符号生成的可执行文件和库会自动包括每个要素目标文件调试符号的副本。如果用 stabs 格式的调试符号生成的可执行文件和库是通过 -xs 选项(该选项将 stabs 符号保留在各个目标文件及可执行文件中)进行链接的,那么所生成的可执行文件和库中也会包括每个要素目标文件调试符号的副本。当您需要移动或删除目标文件时,包括这些信息尤为重要。使用可执行文件和库本身中的所有调试符号,可以更容易地将实验和与程序相关的文件移至新位置。

静态链接

编译程序时,必须使用 -dn-Bstatic 编译器选项打开动态链接。如果试图收集完全静态链接的程序的数据,则收集器会列显一条错误消息并且不收集数据。出现此错误的原因在于,当您运行收集器时,该收集器库也会像其他库一样动态装入。

请不要静态链接任何系统库。如果您执行了静态链接,则可能无法收集任何种类的跟踪数据。另外,请不要链接到收集器库 libcollector.so

共享对象处理

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

编译时优化

如果使用在某一级别打开的优化来编译程序,编译器就可以重新安排执行顺序,这样就无须严格按照程序中行的顺序来执行程序。性能分析器可以分析在优化后的代码中收集的实验,但它在反汇编级别所显示的数据通常很难与初始源代码行相关联。此外,如果编译器执行尾部调用优化,则调用序列可能与预期的序列不同。有关更多信息,请参见尾部调用优化

编译 Java 程序

javac 命令编译 Java 程序无需任何特殊操作。

为数据收集和分析准备程序

对于大多数程序来说,您不必为数据收集和分析做任何特殊的准备。如果程序执行下列任一操作,则应当阅读下面的一个或多个小节:

此外,如果要控制程序中的数据收集,还应当阅读相关小节。

使用动态分配的内存

许多程序依赖于动态分配的内存,它们使用诸如以下各项的功能:

必须小心确保程序不依赖于动态分配的内存的初始内容,除非内存分配方法明确地说明要设置初始值:例如,比较 malloc(3C) 手册页中对 callocmalloc 的描述。

偶尔,使用动态分配的内存的程序似乎可以单独地正常运行,但是启用性能数据收集之后就会失败。症状可能包括意外的浮点行为、段故障或特定于应用程序的错误消息。

如果应用程序单独运行时未初始化的内存偶然设置为良性值,但应用程序与性能数据收集工具一起运行时未初始化的内存被设置为其他值,则会出现这种行为。发生这种情况时,问题不出在性能工具上。依赖于动态分配的内存内容的任何应用程序都具有潜在的错误:除非明确说明使用其他方式,否则操作系统将为动态分配的内存随机提供任意内容。即使目前操作系统会始终将动态分配的内存设置为某个值,但是将来在使用操作系统的后续修订版或将程序移植到其他操作系统时,这些潜在的错误会引起意外的行为。

下列工具可以帮助您找到这些潜在的错误:

使用系统库

收集器插入各种系统库的函数,以收集跟踪数据并确保数据收集的完整性。下面的列表描述了收集器插入库函数调用的情况。

在某些情况下,插入不会成功:

收集器插入失败可能会导致性能数据丢失或无效。

er_sync.soer_heap.soer_mpviewn.so(其中 n 表示 MPI 版本)库仅在分别请求同步等待跟踪数据、堆跟踪数据或 MPI 跟踪数据时装入。

使用信号处理程序

收集器使用两个信号来收集分析数据:SIGPROF 用于所有实验;SIGEMT(在 Solaris 平台上)或 SIGIO(在 Linux 平台上)仅用于硬件计数器实验。收集器为其中的每个信号安装一个信号处理程序。该信号处理程序截获并处理它自己的信号,但是会将其他信号传递到所安装的其他信号处理程序。如果程序为这些信号安装其自己的信号处理程序,则收集器会将其信号处理程序作为主处理程序重新安装,以保证性能数据的完整性。

collect 命令还可以将用户指定的信号用于暂停和恢复数据收集以及记录样本。尽管在安装用户处理程序时向实验中写入警告,但这些信号不受收集器保护。确保收集器对指定信号的使用与应用程序对相同信号的使用之间没有冲突是您的责任。

由收集器安装的信号处理程序会设置一个确保系统调用不被信号传送中断的标志。如果程序的信号处理程序将该标志设置为允许中断系统调用,则设置该标志可以更改程序的行为。在异步 I/O 库 libaio.so 中就有一个行为更改的重要示例,它将 SIGPROF 用于异步取消操作,并且中断系统调用。如果已安装收集器库 libcollector.so则取消信号总是来得太迟,以至于无法取消异步 I/O 操作。

如果在未预装入收集器库的情况下将 dbx 附加到进程并启用性能数据收集,并且程序随后安装其自身的信号处理程序,则收集器不再重新安装其自身的信号处理程序。在这种情况下,程序的信号处理程序必须确保 SIGPROFSIGEMT 信号被传递,以便性能数据不丢失。如果程序的信号处理程序中断系统调用,那么程序行为和分析行为都将与预装入收集器库时不同。

使用 setuidsetgid

由于动态装入器实施了一定的限制,因此将难以使用 setuid(2) 和收集性能数据。如果您的程序调用 setuid 或执行 setuid 文件,则收集器可能无法写入实验文件,原因是它缺少新用户 ID 的必需权限。

collect 命令通过将共享库 libcollector.so 插入目标的地址空间 (LD_PRELOAD) 来运行。如果对调用 setuidsetgid 或创建调用 setuidsetgid 的子孙进程的可执行文件调用过的 collect 命令进行调用,可能会出现多个问题。如果您不是超级用户,在运行实验时,收集会因为共享库未安装在可信目录中而失败。解决方法是以超级用户身份运行实验,或使用 crle(1) 授予权限。应对安全障碍时请格外小心,操作风险需自行承担。

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

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

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

数据收集的程序控制

如果要控制程序中的数据收集,收集器共享库 libcollector.so 包含了一些可以使用的 API 函数。这些函数是用 C 编写的,还提供了一个 Fortran 接口。C 接口和 Fortran 接口都是在由库所提供的头文件中定义的。

API 函数定义如下所示。


void collector_sample(char *name);
void collector_pause(void);
void collector_resume(void);
void collector_terminate_expt(void);

CollectorAPI 类为 Java 程序提供了类似的功能,Java 接口中对其进行了介绍。

C 和 C++ 接口

可以通过包括 collectorAPI.h 并与 -lcollectorAPI(包含用于检查底层 libcollector.so API 函数是否存在的实际函数)相链接来访问收集器 API 的 C 和 C++ 接口。

如果没有活动的实验,API 调用将被忽略。

Fortran 接口

Fortran API libfcollector.h 文件定义了库的 Fortran 接口。要使用该库,必须使用 -lcollectorAPI 链接应用程序。(还提供了该库的替代名称 -lfcollector,目的在于实现向后兼容性。除动态函数、线程暂停和恢复调用等功能外,Fortran API 提供了与 C 和 C++ API 相同的功能。

要使用 Fortran 的 API 函数,请插入下面的语句:


include "libfcollector.h"

注 –

请勿使用 -lcollector 链接任何语言的程序。否则,收集器可能会出现不可预知的行为。


Java 接口

使用以下语句导入 CollectorAPI 类并访问 Java API。但是请注意,必须使用指向 /installation_directory/lib/collector.jar 的类路径来调用应用程序,其中 installation_directory 是 Oracle Solaris Studio 软件的安装目录。


import com.sun.forte.st.collector.CollectorAPI;

Java CollectorAPI 方法的定义如下所示:


CollectorAPI.sample(String name)
CollectorAPI.pause()
CollectorAPI.resume()
CollectorAPI.terminate()

除动态函数 API 之外,Java API 包含与 C 和 C++ API 相同的函数。

C 头文件 libcollector.h 包含一些宏,这些宏的作用是如果当时未在收集数据,则跳过对实际 API 函数的调用。在这种情况下,不动态装入函数。但是,由于在某些情况下这些宏不能很好地运行,所以使用这些宏会有风险。使用 collectorAPI.h 较为安全,因为它不使用宏,而是直接引用函数。

如果正在收集性能数据,则 Fortran API 子例程会调用 C API 函数,否则这些子例程将返回。检查的开销很低,不会对程序性能产生太大的影响。

如本章稍后所述,要收集性能数据就必须使用收集器运行您的程序。插入对 API 函数的调用不会启用数据收集功能。

如果要在多线程程序中使用 API 函数,应当确保它们只由一个线程调用。API 函数执行适用于进程(而不是单独的线程)的操作。如果每个线程都调用 API 函数,则记录的数据可能会与预期不同。例如,如果一个线程在其他线程到达程序中的同一点之前调用了 collector_pause()collector_terminate_expt(),则会针对所有线程暂停或终止收集,从而丢失那些正在执行 API 调用之前代码的线程的数据。

C、C++、Fortran 和 Java API 函数

对 API 函数的描述如下所示。

动态函数和模块

如果 C 或 C++ 程序向程序的数据空间动态编译函数,而且您希望在性能分析器中查看动态函数或模块的数据,那么,您必须向收集器提供信息。该信息由对收集器 API 函数的调用传递。API 函数的定义如下所示。


void collector_func_load(char *name, char *alias,
    char *sourcename, void *vaddr, int size, int lntsize,
    Lineno *lntable);
void collector_func_unload(void *vaddr);

您不必将这些 API 函数用于由 Java HotSpot 虚拟机编译的 Java 方法,该虚拟机使用的是另一个接口。Java 接口提供已编译到收集器的方法的名称。您可以查看 Java 编译方法的函数数据和带注释的反汇编列表,但不能查看带注释的源代码列表。

对 API 函数的描述如下所示。

collector_func_load()

将有关动态编译的函数的信息传递到收集器,以便在实验中进行记录。下表对参数列表进行了描述。

表 3–1 collector_func_load() 的参数列表

参数 

定义 

name

性能工具所使用的动态编译函数的名称。该名称不必是函数的实际名称。虽然该名称不应包含嵌入的空格或引号字符,但无须遵循通常的函数命名约定。 

alias

用于描述函数的任意字符串。它可以是 NULL。它不经过任何方式的解释,可以包含嵌入的空格。它显示在分析器的“摘要”标签中。它可用于指示函数的内容或动态构造函数的原因。

sourcename

构造函数时所在源文件的路径。它可以是 NULL。该源文件用于带注释的源代码列表。

vaddr

函数的装入地址。 

size

以字节为单位的函数大小。 

lntsize

对行号表中条目数量的计数。如果未提供行号信息,则计数应为零。 

lntable

包含 lntsize 条目的表,其中每个条目都是一对整数。第一个整数是偏移量,第二个整数是行号。在一个条目的偏移量和下一个条目中所给出的偏移量之间的所有指令都归属于在第一个条目中提供的行号。偏移量必须按数字升序列出,但行号的顺序可以是任意的。如果 lntableNULL,没有可用的函数源代码列表,但是反汇编列表是可用的。

collector_func_unload()

通知收集器位于地址 vaddr 的动态函数已卸载。

数据收集的限制

本节描述了数据收集的限制,这些限制是由硬件、操作系统、程序的运行方式或收集器本身造成的。

对同时收集不同类型的数据来说,没有任何限制:您可以在收集某种数据类型的同时收集除计数数据以外的任何其他数据类型。

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

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

基于时钟的分析的限制

用于分析的分析间隔最小值和时钟精度取决于特定的操作环境。最大值设置为 1 秒。分析间隔值将向下舍入到最接近的时钟精度的整数倍。可以通过键入不带参数的 collect 命令来查找最小值和最大值以及时钟精度。

时钟分析中的运行时失真和扩大

基于时钟的分析记录当 SIGPROF 信号传递到目标时的数据。这将导致在处理该信号和展开调用栈时产生扩大。调用栈越深,信号越频繁,扩大越显著。在一定程度上,基于时钟的分析表现出一些失真,这是由程序中那些执行最深栈部分的显著扩大而导致的。

请尽可能不要将缺省值设置为一个精确的毫秒数,而是将其设置为稍大于或稍小于某个精确数(例如,10.007 毫秒或 0.997 毫秒),以免与系统时钟关联,从而避免数据失真。在 SPARC 平台上,可以按照同样的方式来设置定制值(在 Linux 平台上不能设置定制值)。

收集跟踪数据的限制

只有在已预装入收集器库 libcollector.so 的情况下,才可以从已在运行的程序中收集任何种类的跟踪数据。有关更多信息,请参见从正在运行的程序中收集跟踪数据

跟踪过程中的运行时失真和扩大

跟踪数据使运行与被跟踪事件的数量成比例地扩大。如果完成了基于时钟的分析,则跟踪事件所引起的扩大将导致时钟数据失真。

硬件计数器溢出分析的限制

硬件计数器溢出分析存在多种限制:

硬件计数器溢出分析中的运行时失真和扩大

硬件计数器溢出分析记录当 SIGEMT 信号(在 Solaris 平台上)或 SIGIO 信号(在 Linux 平台上)传递到目标时的数据。这将导致在处理该信号和展开调用栈时产生扩大。与基于时钟的分析不同的是,对于某些硬件计数器,程序的不同部分可能会比其他部分更快速地生成事件并显示在该部分代码中的扩大。程序中快速生成这类事件的任何部分都可能会显著失真。类似地,某些事件可能会在一个线程中与其他线程不成比例地生成。

对子孙进程进行数据收集的限制

可以在某些限制下对子孙进程进行数据收集。

如果要在收集器所跟踪的所有子孙进程中收集数据,使用 collect 命令时必须带有下列选项之一:

有关 -F 选项的更多信息,请参见实验控制选项

OpenMP 分析的限制

在执行程序期间收集 OpenMP 数据开销可能很大。可以通过设置 SP_COLLECTOR_NO_OMP 环境变量来压低开销。如果这样做,程序执行时间将显著缩短,但是将看不到自从属线程向上传播到调用方并最终传播到 main() 的数据,而在未设置该变量时通常情况下将能看到这些数据。

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

OpenMP 分析功能仅对使用 Oracle Solaris Studio 编译器编译的应用程序可用,因为它取决于 Oracle Solaris Studio 编译器运行时。对于使用 GNU 编译器编译的应用程序,仅显示机器级别的调用栈。

Java 分析的限制

可以在下列限制下在 Java 程序中收集数据:

用 Java 编程语言所编写的应用程序的运行时性能失真和扩大

Java 分析功能使用的 Java 虚拟机工具接口 (Java Virtual Machine Tool Interface, JVMTI) 可能会导致运行的失真和扩大。

对于基于时钟的分析和硬件计数器溢出分析,数据收集进程会对 JVM 软件进行各种调用,并使用信号处理程序处理分析事件。这些例程的开销和将实验写入磁盘的代价将扩大 Java 程序的运行时。这种扩大通常小于 10%。

数据的存储位置

应用程序的一次执行过程中所收集的数据称作实验。实验由存储在目录下的一组文件组成。实验的名称即目录的名称。

除记录实验数据以外,收集器还为程序所使用的装入对象创建自己的归档文件。这些归档文件包含装入对象中每个目标文件和函数的地址、大小和名称以及装入对象的地址和上次修改的时间戳。

缺省情况下,实验存储在当前目录中。如果该目录位于网络文件系统上,则存储数据所需的时间比在本地文件系统中长,而且可能会导致性能数据失真。如有可能,应始终尝试在本地文件系统中记录实验。可以在运行收集器时指定存储位置。

子孙进程的实验存储在创始进程的实验内部。

实验名称

新实验的缺省名称为 test.1.er。后缀 .er 是必需的:如果您赋予的名称不具有该后缀,则系统会显示一条错误消息而且不接受该名称。

如果您选择使用格式为 experiment.n.er 的名称,(其中 n 是正整数),则收集器会将后续实验名称中的 n 自动递增 1。例如,mytest.1.er 的后面是 mytest.2.ermytest.3.er 等。如果实验已经存在,收集器也会递增 n,直到找到未使用的实验名称才停止递增 n。如果实验名称不含 n 且实验存在,则收集器会列显一条错误消息。

实验可按组收集。组在实验组文件中定义,缺省情况下该文件存储在当前目录中。实验组文件是纯文本文件,它具有特殊的标题行,并在随后的每一行中显示实验名称。实验组文件的缺省名称为 test.erg如果名称不以 .erg 结尾,则系统会显示一条错误并且不接受该名称。创建实验组后,您使用该组名运行的所有实验都会添加到该组中。

可以手动创建实验组文件,方法是创建第一行是如下内容的纯文本文件


#analyzer experiment group

然后将实验名称添加到随后的行中。文件的名称必须以 .erg 结尾。

还可以通过使用带有 -g 参数的 collect 命令来创建实验组。

子孙进程的实验是沿袭命名的,如下所示。要形成子孙进程的实验名称,可将下划线、代码字母和数字添加到其创建者实验名称的主干中。代码字母 f 表示派生,x 表示执行,c 表示组合。数字是派生或执行的索引(无论是否成功)。例如,如果创始进程的实验名称为 test.1.er,则在第三次调用 fork 时为子进程创建的实验为 test.1.er/_f3.er。如果该子进程成功调用 exec,新子孙进程的实验名称为 test.1.er/_f3_x1.er

移动实验

如果要将实验移到其他计算机以便对其进行分析,则应了解分析对在其中记录实验的操作环境的依赖性。

归档文件包含计算函数级度量和显示时间线所必需的全部信息。但是,如果要查看带注释的源代码或带注释的反汇编代码,则必须能够访问与记录实验时所用装入对象或源文件相同的版本。

性能分析器在下列位置依次搜索源代码、对象和可执行文件,并在找到具有正确基本名称的文件时停止:

可以从分析器 GUI 或通过使用 setpath(请参见setpath path_list)和 addpath(请参见addpath path_list)指令来更改搜索顺序或添加其他搜索目录。还可以使用 pathmap 命令扩大搜索。

为了确保能够看到程序的正确的带注释源代码和带注释反汇编代码,可以在移动或复制实验之前将源代码、目标文件和可执行文件复制到该实验中。如果您不想复制目标文件,则可以使用 -xs 来链接程序,以确保源代码行和文件位置上的信息插入可执行文件中。可以通过使用 collect 命令的 -A copy 选项或 dbx collector archive 命令将装入对象自动复制到实验中。

估计存储要求

本节就如何对记录实验所需的磁盘空间量进行估计提供了一些指导。实验的大小直接取决于数据包的大小、记录数据包的速率、程序使用的 LWP 的数量和程序的执行时间。

数据包中包含特定于事件的数据和取决于程序结构(调用栈)的数据。取决于数据类型的数据量约为 50 到 100 个字节。调用栈数据由每个调用的返回地址组成,每个地址包含 4 个字节(在 64 位可执行文件中为 8 个字节)。记录了实验中的每个 LWP 的数据包。请注意,对于 Java 程序,有两个相关的调用栈:Java 调用栈和机器调用栈,因此将导致向磁盘中写入更多的数据。

记录分析数据包的速率由时钟数据的分析间隔和硬件计数器数据的溢出值控制,对于跟踪函数,是跟踪函数出现的速率。对于分析间隔参数的选择也会因数据收集的开销而影响数据质量和程序性能的失真。这些参数的值越小,提供的统计信息越好,但开销也会越大。为了在获得较好统计信息和尽可能降低开销之间实现折衷,我们已经为分析间隔和溢出值精心选择了缺省值。值越小,数据越多。

对于分析间隔大约为每秒 100 个样本、数据包大小范围从 80 字节(对于小调用栈)到最多 120 字节(对于大调用栈)的基于时钟的分析实验或硬件计数器溢出分析实验,将以每个线程每秒 10 千字节的速率记录数据。调用栈深度为数百个调用的应用程序可以很轻松地以十倍的速率记录数据。

对于 MPI 跟踪实验,数据量为每个跟踪 MPI 调用 100-150 字节,具体取决于发送的消息数和调用栈的深度。此外,在使用 collect 命令的 -M 选项时,缺省情况下会启用时钟分析,因此,请为时钟分析实验添加估计的数字。可以通过使用 -p off 选项禁用时钟分析来减少 MPI 跟踪的数据量。


注 –

收集器以自己的格式 (mpview.dat3) 存储 MPI 跟踪数据,还以 VampirTrace OTF 格式 (a.otf, a.*.z) 存储 MPI 跟踪数据。可以删除 OTF 格式的文件而不影响分析器。


在估计实验大小时,还应当考虑归档文件所占用的磁盘空间,它通常是所要求的总磁盘空间的一小部分(请参见上一节)。如果您无法确定所需空间的大小,请尝试运行实验一小会儿。通过该测试,可以得到与数据收集时间无关的归档文件大小,然后对分析文件的大小进行放大以获得全长实验的估计大小。

除了分配磁盘空间之外,收集器还在内存中分配缓冲区,以便在将分析数据写入磁盘之前对其进行存储。目前无法指定这些缓冲区的大小。如果收集器用完了内存,请尝试减少所收集的数据量。

如果存储实验所需的估计空间大于可用空间,请考虑收集部分运行(而不是全部运行)的数据。要收集部分运行的数据,可以使用带有 -y-t 选项的 collect 命令或 dbx collector 子命令,也可以在程序中插入对收集器 API 的调用。还可以对由带有 -L 选项的 collect 命令或 dbx collector 子命令所收集的分析和跟踪数据总量进行限制。

收集数据

性能分析器可以使用以下多种方式收集性能数据:

只有“Oracle Solaris Studio 收集”对话框和 collect 命令提供下列数据收集功能:

使用 collect 命令收集数据

要从命令行使用 collect 命令运行收集器,请键入以下内容。


% collect collect-options program program-arguments

其中,collect-optionscollect 命令选项program 是要收集其数据的程序的名称,program-arguments 是该程序的参数。目标程序通常是二进制可执行文件。但是,如果设置环境变量 SP_COLLECTOR_SKIP_CHECKEXEC,可以将脚本指定为目标。

如果未提供 collect-options,则缺省情况下会打开分析间隔大约为 10 毫秒的基于时钟的分析。

要获取可用于分析的选项列表和所有硬件计数器的名称列表,请键入不带参数的 collect 命令。


% collect

有关对硬件计数器列表的描述,请参见硬件计数器溢出分析数据。另请参见硬件计数器溢出分析的限制

数据收集选项

这些选项控制所收集数据的类型。有关对数据类型的介绍,请参见收集器收集何种数据

如果未指定数据收集选项,则缺省值为 -p on,这会启用缺省分析间隔大约为 10 毫秒的基于时钟的分析。该缺省值由 -h 选项关闭,而不是由任何其他数据收集选项关闭。

如果您明确禁用了基于时钟的分析,而且未启用跟踪或硬件计数器溢出分析,则 collect 命令会列显一条警告消息,并且只收集全局数据。

-p option

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

collect 命令的缺省操作是收集基于时钟的分析数据。

-h counter_definition_1...[, counter_definition_n]

收集硬件计数器溢出分析数据。计数器定义的数量与处理器有关。

如果安装了 perfctr 修补程序(可以从 http://user.it.uu.se/~mikpe/linux/perfctr/2.6/ 下载),该选项在运行 Linux 操作系统的系统上是可用的。安装说明包含在 tar 文件中。使用 LD_LIBRARY_PATH 环境变量的值搜索用户级 libperfctr.so 库,即:对于 32 位版本,在 /usr/local/lib/usr/lib/lib 中进行搜索;对于 64 位版本,在 /usr/local/lib64/usr/lib64/lib64 中进行搜索。

要获取可用计数器的列表,请在终端窗口中键入不带参数的 collect硬件计数器列表一节提供了对计数器列表的介绍。在大多数系统上,即使未列出计数器,仍可以使用数值(十六进制或十进制)对其进行指定。

计数器定义可以采用下列形式之一,具体取决于处理器是否支持硬件计数器的属性。

[+]counter_name[/ register_number][,interval ]

[+]counter_name[~ attribute_1=value_1]...[~attribute_n =value_n][/ register_number][,interval ]

特定于处理器的 counter_name 可以为下列名称之一:

如果指定了多个计数器,则它们必须使用不同的寄存器。如果它们未使用不同的寄存器,则 collect 命令会列显一条错误消息并退出。

如果硬件计数器对与内存访问有关的事件进行计数,可以在计数器名称前添加 + 符号,以针对引起计数器溢出的指令打开对其真实程序计数器地址 (counter address, PC) 的搜索。这种回溯功能适用于 SPARC 处理器,并且仅适用于类型为 loadstoreload-store 的计数器。如果搜索成功,则所引用的虚拟 PC、物理 PC 和有效地址将存储在事件数据包中。

在某些处理器上,可以将多个属性选项与一个硬件计数器关联。如果某个处理器支持多个属性选项,则运行不带参数的 collect 命令会列出计数器定义(包括属性名)。可以使用十进制或十六进制格式来指定属性值。

间隔(溢出值)是事件计数或循环计数的数量,在达到该数量时,硬件计数器将溢出并且将记录溢出事件。间隔可以设置为下列值之一:

缺省值是为每个计数器预定义的正常阈值,它出现在计数器列表中。另请参见硬件计数器溢出分析的限制

如果在使用 -h 选项时未明确指定 -p 选项,则基于时钟的分析功能将处于关闭状态。要同时收集硬件计数器数据和基于时钟的数据,必须同时指定 -h 选项和 -p 选项。

-s option

收集同步等待跟踪数据。option 的允许值包括:

对于 Java 程序,不能记录同步等待跟踪数据;如果指定它,将视为错误。

在 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()

-H option

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

缺省情况下,堆跟踪功能处于关闭状态。对于 Java 程序,不支持堆跟踪;如果指定堆跟踪,将被视为错误。

-M option

指定对 MPI 实验的收集。collect 命令的目标必须为 mpirun 命令,必须使用 ‐‐ 选项将 mpirun 的选项与要使用 mpirun 命令运行的目标程序分开。(始终将 -- 选项和 mpirun 命令一起使用,以便可以通过将 collect 命令及其选项前置于 mpirun 命令行来收集实验。)实验按惯常方式命名且称为创始实验,其目录包含每个 MPI 进程的子实验,按等级进行命名。

option 的允许值包括:

缺省情况下,MPI 实验的收集功能是关闭的。打开 MPI 实验的收集功能时,-m 选项的缺省设置更改为 on

键入不带选项的 collect 命令时,或者如果使用 -M 选项指定无法识别的版本,将会列显受支持的 MPI 版本。

-m option

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

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

有关其调用被跟踪的 MPI 函数以及根据跟踪数据计算的度量的更多信息,请参见MPI 跟踪数据

-S option

定期记录样本包。option 的允许值包括:

缺省情况下,启用间隔为 1 秒的定期抽样功能。

-c option

记录计数数据,仅针对 Solaris 系统。


注 –

此功能要求您安装 Binary Interface Tool (BIT),它是 Add-on Cool Tools for OpenSPARC(适用于 OpenSPARC 的附加酷类工具)的一部分(可从 http://cooltools.sunsource.net/ 获取)。BIT 是用来度量 Solaris 二进制代码的性能或测试套件适用范围的工具。


option 的允许值包括:

缺省情况下,关闭对计数数据的收集。计数数据不能和任何其他类型的数据一起收集。

-I directory

bit 检测指定目录。该选项仅在 Solaris 系统上可用,且仅当指定了 -c 选项时才有意义。

-N library_name

指定要从 bit 检测中排除的库,不管该库是链接到可执行文件还是使用 dlopen() 装入。该选项仅在 Solaris 系统上可用,且仅当指定了 -c 选项时才有意义。可以指定多个 -N 选项。

-r option

为线程分析器收集数据争用检测或死锁检测数据。允许的值包括:

有关 collect -r 命令和线程分析器的更多信息,请参见《Oracle Solaris Studio 12.2:线程分析器用户指南》tha(1) 手册页。

实验控制选项

这些选项控制如何收集实验数据。

-F option

控制是否应当记录子孙进程的数据。option 的允许值包括:

缺省情况下设置 -F on 选项,这样收集器将跟踪通过调用函数 fork(2)、fork1(2)、fork(3F)、vfork(2) 和 exec(2) 及其变体而创建的进程。对 vfork 的调用已在内部被替换为对 fork1 的调用。

对于 MPI 实验,缺省情况下还跟踪子孙进程。

如果指定 -F all 选项,收集器将跟踪所有子孙进程,其中包括那些通过调用 system(3C)、system(3F)、sh(3F)、posix_spawn(3p)、posix_spawnp(3p) 和 popen(3C) 以及类似函数而创建的子孙进程以及与其相关的子孙进程。

如果指定 -F '= regexp ' 选项,收集器将跟踪所有子孙进程。当子孙进程的名称或子实验的名称与指定的正则表达式匹配时,收集器将创建子实验。有关正则表达式的信息,请参见 regexp(5) 手册页。

当您在子孙进程上收集数据时,收集器会针对创始实验中的每个子孙进程打开一个新实验。这些新实验是通过向实验后缀添加一个下划线、一个字母和一个数字来命名的,如下所示:

例如,如果初始进程的实验名称是 test.1.er,则由它的第三个派生创建的子进程的实验是 test.1.er/_f3.er。如果该子进程针对新映像执行 exec 操作,则相应的实验名称为 test.1.er/_f3_x1.er。如果该子进程使用 popen 调用创建另一个进程,则实验名称为 test.1.er/_f3_x1_c1.er

读取创始实验时,分析器和 er_print 实用程序将自动读取子孙进程的实验,并在数据显示中显示子孙进程。

要从命令行中选择要显示的数据,请明确指定 er_printanalyzer 的路径名。所指定的路径必须包含创始实验的名称以及创始目录中后续实验的名称。

例如,要查看 test.1.er 实验的第三个派生的数据,需要指定以下内容:

er_print test.1.er/_f3.er

analyzer test.1.er/_f3.er

或者,可以使用感兴趣的后续实验的显式名称来准备实验组文件。

要在分析器中检查子孙进程,请装入创始实验并从“视图”菜单中选择“过滤数据”。此时将显示一个实验列表,其中只有创始实验处于选中状态。取消选中初始实验并选中感兴趣的后续实验。


注 –

如果正在跟踪子孙进程时创始进程退出,将继续从仍然在运行的子孙进程中收集数据。创始实验目录会相应地继续变大。


您还可以收集脚本上的数据并跟踪脚本的子孙进程。有关更多信息,请参见从脚本收集数据

-j option

当目标程序是 JVM 时,启用 Java 分析。option 的允许值包括:

如果要收集 .class 文件或 .jar 文件中的数据,则不需要 -j 选项,但前提是 java 可执行文件的路径在 JDK_HOME 环境变量或 JAVA_PATH 环境变量中。随后可以在 collect 命令行上将目标 program 指定为具有或不具有扩展名的 .class 文件或 .jar 文件。

如果无法在 JDK_HOMEJAVA_PATH 环境变量中定义 java 可执行文件的路径,或者要禁用对 Java HotSpot 虚拟机所编译的方法的识别,则可以使用 -j 选项。如果使用此选项,在 collect 命令行上指定的 program 必须为版本不低于 JDK 6 Update 18 的 Java 虚拟机。collect 命令验证 program 是否为 JVM 且是 ELF 可执行文件,如果不是,collect 命令将列显一条错误消息。

如果要使用 64 位 JVM 收集数据,则不得对 32 位 JVM 的 java 命令使用 -d64 选项。否则,将收集不到任何数据。而是,必须在 collect 命令的 program 参数中或者在 JDK_HOMEJAVA_PATH 环境变量中指定 64 位 JVM 的路径。

-J java_argument

指定要传递到用于分析的 JVM 的其他参数。如果您指定了 -J 选项但未指定 Java 分析,则会生成一个错误并且不运行实验。如果 java_argument 包含多个参数,则必须使用括号将其括起来。它必须包括一组由空格或制表符分隔的令牌。每个令牌作为单独的参数传递给 JVM。JVM 的大多数参数必须以 "-" 字符开头。

-l signal

名为 signal 的信号传递到进程时,记录样本包。

可以通过全信号名、不带开始的几个字母 SIG 的信号名或信号编号来指定信号。请不要使用程序所使用的信号或会终止执行的信号。建议的信号为 SIGUSR1SIGUSR2。即使指定时钟分析,也可以使用 SIGPROF。可通过 kill 命令将信号传递到进程。

如果同时使用 -l-y 选项,则必须针对每个选项使用不同的信号。

如果您使用该选项而程序具有其自己的信号处理程序,则应当确保使用 -l 指定的信号会传递到收集器的信号处理程序,而不是被截获或忽略。

有关信号的更多信息,请参见 signal(3HEAD) 手册页。

-t duration

指定数据收集的时间范围。

可以将 duration 指定为单个数字(可以选择添加 ms 后缀)以指示实验在该时间(单位为分钟或秒)终止。缺省情况下,持续时间以秒为单位。也可以将 duration 指定为用连字符分隔的两个这样的数字,这会导致数据收集暂停,直到经过第一个时间之后才开始收集数据。当到达第二个时间时,数据收集终止。如果第二个数字为零,则在初次暂停之后收集数据,直到该程序运行结束。即使该实验已经终止,也允许目标进程运行至结束。

-x

在从 exec 系统调用退出时使目标进程停止,以便允许调试器附加到目标进程。如果将 dbx 附加到目标进程,请使用 dbx 命令 ignore PROFignore EMT 来确保收集信号传递到 collect 命令。

-y signal[ ,r]

控制对包含名为 signal 的信号的数据的记录。无论何时将信号传递到进程,它都在暂停状态(在此期间不记录任何数据)和记录状态(在此期间记录数据)之间切换。无论切换状态如何,都将始终记录样本点。

可以通过全信号名、不带开始的几个字母 SIG 的信号名或信号编号来指定信号。请不要使用程序所使用的信号或会终止执行的信号。建议的信号为 SIGUSR1SIGUSR2。即使指定时钟分析,也可以使用 SIGPROF。可通过 kill 命令将信号传递到进程。

如果同时使用 -l-y 选项,则必须针对每个选项使用不同的信号。

使用 -y 选项时,如果已提供可选的 r 参数,则收集器将在记录状态下启动,否则将在暂停状态下启动。如果未使用 -y 选项,则收集器将在记录状态下启动。

如果您使用该选项而程序具有其自己的信号处理程序,则应当确保使用 -y 指定的信号会传递到收集器的信号处理程序,而不是被截获或忽略。

有关信号的更多信息,请参见 signal(3HEAD) 手册页。

输出选项

这些选项控制收集器生成实验的各个方面。

-o experiment_name

使用 experiment_name 作为要记录的实验的名称。experiment_name 字符串必须以字符串 ".er" 结尾;否则 collect 实用程序会列显一条错误消息并退出。

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

如果您要从用于运行 MPI 作业的命令之一(例如 mpirun,但不带 -M MPI-version 选项和 -o 选项)调用 collect 命令,则采用用于定义该进程的 MPI 等级的环境变量的名称中使用的值 n。否则,将 n 设置为比当前使用的最大整数还要大的值。

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

-d directory-name

将实验置于 directory-name 目录中。此选项仅适用于个别实验,而不适用于实验组。如果该目录不存在,则 collect 实用程序会列显一则错误消息并退出。如果使用 -g 选项指定了某个组,则该组文件也将写入 directory-name 中。

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

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

-g group-name

使实验成为实验组 group-name 的一部分。如果 group-name 不以 .erg 结尾,则 collect 实用程序会列显一条错误消息并退出。如果该组存在,则会将实验添加到该组中。如果 group-name 不是绝对路径并且使用 -d 指定了一个目录,则实验组将被置于 directory-name 目录中,否则,将被置于当前目录中。

-A option

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

如果您希望将实验从记录的位置复制到另一台计算机,或者从另一台计算机读取实验,请指定 - A copy。使用该选项不会将任何源文件或目标 (.o) 文件复制到实验中。确保可从在其上检查实验的计算机访问这些文件且这些文件未发生更改。

-L size

将所记录的分析数据量限制在 size 兆字节。该限制适用于基于时钟的分析数据量、硬件计数器溢出分析数据量和同步等待跟踪数据量之和,但不适用于样本点。该限制只是近似值,可以被超出。

当达到该限制时,不再记录分析数据,但实验会一直保持打开状态,直到目标进程终止。如果启用了定期抽样,则会继续写入样本点。

例如,要将限制确定为约 2 GB,请指定 -L 2000。指定的大小必须大于零。

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

-O file

collect 本身的所有输出附加到名称 file,但是不重定向所产生的目标的输出。如果该文件设置为 /dev/null,则禁止 collect 的所有输出(包括任何错误消息)。

其他选项

这些 collect 命令选项用于其他目的。

-P process_id

编写 dbx 脚本以附加到具有给定 process_id 的进程,从中收集数据,然后在脚本中调用 dbx。可以仅指定分析数据而不指定跟踪数据,且不支持定时运行(-t 选项)。

-C comment

将注释放在实验的 notes 文件中。最多可以提供十个 -C 选项。该 notes 文件的内容会置于实验标题的前面。

-n

不运行目标,但列显在运行目标时要生成的实验的详细信息。此选项是模拟运行选项。

-R

在终端窗口中显示性能分析器自述文件的文本版本。如果未找到自述文件,则列显一条警告。不再检查任何参数,也不执行进一步的处理。

-V

列显 collect 命令的当前版本。不再检查任何参数,也不执行进一步的处理。

-v

列显 collect 命令的当前版本和正在运行的实验的详细信息。

使用 collect 实用程序从正在运行的进程中收集数据

仅在 Solaris OS 中,可以将 -P pid 选项与 collect 实用程序一起使用来附加到具有指定 PID 的进程并从该进程收集数据。collect 命令的其他选项被转换为 dbx 脚本,系统会调用该脚本来收集数据。只能收集基于时钟的分析数据(-p 选项)和硬件计数器溢出分析数据(-h 选项)。不支持跟踪数据。

如果在使用 -h 选项时未明确指定 -p 选项,则基于时钟的分析功能将处于关闭状态。要同时收集硬件计数器数据和基于时钟的数据,必须同时指定 -h 选项和 -p 选项。

Procedure使用 collect 实用程序从正在运行的进程中收集数据

  1. 确定程序的进程 ID (process ID, PID)。

    如果从命令行启动了程序并将其置于后台,shell 将在标准输出中列显其 PID。否则,可以通过键入以下内容来确定程序的 PID。


    % ps -ef | grep program-name
    
  2. 使用 collect 命令对该进程启用数据收集,并设置任何可选参数。


    % collect -P pid collect-options
    

    数据收集选项中对收集器选项进行了说明。有关基于时钟的分析的信息,请参见-p option。有关硬件时钟分析的信息,请参见 -h option

使用 dbx collector 子命令收集数据

本节介绍如何从 dbx 运行收集器,然后介绍可以与 dbx 中的 collector 命令一起使用的每个子命令。

Proceduredbx 运行收集器:

  1. 通过键入以下命令将程序装入 dbx 中。


    % dbx program
    
  2. 使用 collector 命令启用数据收集,选择数据类型并设置任何可选参数。


    (dbx) collector subcommand
    

    要获取可用 collector 子命令的列表,请键入:


    (dbx) help collector
    

    必须针对每个子命令都使用一个 collector 命令。

  3. 设置要使用的任何 dbx 选项并运行该程序。

    如果提供的子命令不正确,则会列显一条警告消息并忽略该子命令。下面是 collector 子命令的完整列表。

数据收集子命令

以下子命令可与 dbx 中的 collector 命令一起使用,对收集器收集的数据的类型进行控制。如果实验处于活动状态,则这些子命令将被忽略并显示一条警告。

profile option

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

hwprofile option

控制对硬件计数器溢出分析数据的收集。如果您尝试在不支持硬件计数器溢出分析的系统中启用它,则 dbx 会返回一条警告消息,而且该命令将被忽略。option 的允许值包括:

synctrace option

控制对同步等待跟踪数据的收集。option 的允许值包括:

heaptrace option

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

缺省情况下,收集器不收集堆跟踪数据。

tha option

为线程分析器收集数据争用检测或死锁检测数据。允许的值包括:

有关线程分析器的更多信息,请参见《Oracle Solaris Studio 12.2:线程分析器用户指南》tha.1 手册页。

sample option

控制抽样模式。option 的允许值包括:

缺省情况下,启用抽样间隔 value 为 1 秒的定期抽样。

dbxsample { on | off }

控制dbx 停止目标进程时对样本的记录。关键字的含义如下所示:

缺省情况下,在 dbx 停止目标进程时记录样本。

实验控制子命令

以下子命令可与 dbx 中的 collector 命令一起使用,对收集器收集的实验数据进行控制。如果实验处于活动状态,将忽略这些子命令并显示一条警告。

disable

禁用数据收集功能。如果进程正在运行而且正在收集数据,该子命令将终止实验并禁用数据收集功能。如果进程正在运行而且数据收集功能处于禁用状态,则该子命令将被忽略并显示一条警告。如果没有任何进程在运行,则该子命令将针对后续运行禁用数据收集功能。

enable

启用数据收集功能。如果进程正在运行,但数据收集功能处于禁用状态,则该子命令将启用数据收集功能并启动新的实验。如果进程正在运行,而且数据收集功能处于启用状态,则该子命令将被忽略并显示一条警告。如果没有任何进程在运行,则该子命令将针对后续运行启用数据收集功能。

您可以在任何进程执行期间根据需要启用和禁用数据收集功能任意次数。每次启用数据收集功能时,都会创建一个新实验。

pause

暂停数据收集,但使实验保持打开状态。收集器暂停时不记录样本点。在暂停之前会生成一个样本,在恢复之后会立即生成另一个样本。如果已暂停数据收集功能,则该子命令将被忽略。

resume

发出 pause 之后恢复数据收集。如果正在收集数据,则该子命令将被忽略。

sample record name

记录具有标签 name 的样本包。该标签显示在性能分析器的“事件”标签中。

输出子命令

以下子命令可与 dbx 中的 collector 命令一起使用,对实验的存储选项进行定义。如果实验处于活动状态,将忽略这些子命令并显示一条警告。

archive mode

设置归档实验的模式。mode 的允许值包括:

如果打算将实验移到另一台计算机上,或者从另一台计算机上读取实验,则应当启用对装入对象的复制。如果实验处于活动状态,则该命令将被忽略并显示一条警告。该命令不会将源文件或目标文件复制到实验中。

limit value

所记录的分析数据量限制在 value 兆字节。该限制适用于基于时钟的分析数据量、硬件计数器溢出分析数据量和同步等待跟踪数据量之和,但不适用于样本点。该限制只是近似值,可以被超出。

当达到该限制时,不再记录分析数据,但实验会一直保持打开状态,而且会继续记录样本点。

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

store option

控制实验的存储位置。如果实验处于活动状态,则该命令将被忽略并显示一条警告。option 的允许值包括:

信息子命令

以下子命令可与 dbx 中的 collector 命令一起使用,从而获取关于收集器设置和实验状态的报告。

show

显示每个收集器控件的当前设置。

status

报告任何打开的实验的状态。

在 Solaris 平台上使用 dbx 从正在运行的进程中收集数据

在 Solaris 平台上,使用收集器可以从正在运行的进程中收集数据。如果进程已受 dbx 的控制,则可以暂停该进程并使用前几节中所描述的方法来启用数据收集。Linux 平台不支持在正在运行的进程上启动数据收集。

如果进程不受 dbx 的控制,则可以使用 collect -Ppid 命令从正在运行的进程中收集数据,如使用 collect 实用程序从正在运行的进程中收集数据中所述。您还可以向其附加 dbx,收集性能数据,然后从该进程分离并使进程继续运行。如果要为选定的子孙进程收集性能数据,必须将 dbx 附加到每个进程。

Procedure从不受 dbx 控制的正在运行的进程中收集数据

  1. 确定程序的进程 ID (process ID, PID)。

    如果从命令行启动了程序并将其置于后台,shell 将在标准输出中列显其 PID。否则,可以通过键入以下内容来确定程序的 PID。


    % ps -ef | grep program-name
    
  2. 附加到该进程。

    dbx 键入以下内容。


    (dbx) attach program-name pid
    

    如果 dbx 尚未运行,请键入以下内容。


    % dbx program-name pid
    

    附加到正在运行的进程会使该进程暂停。

    有关附加到进程的更多信息,请参见手册《Oracle Solaris Studio 12.2:使用 dbx 调试程序》

  3. 启动数据收集功能。

    dbx 中,使用 collector 命令来设置数据收集参数,使用 cont 命令来恢复执行进程。

  4. 从进程中分离。

    在完成对数据的收集之后,暂停该程序并从 dbx 中分离该进程。

    dbx 键入以下内容。


    (dbx) detach
    

从正在运行的程序中收集跟踪数据

如果要收集任何种类的跟踪数据,则必须在运行程序之前预装入收集器库 libcollector.so。要收集堆跟踪数据或同步等待跟踪数据,还必须分别预装入 er_heap.soer_sync.so。这些库提供了能使数据收集发生的实际函数的包装。此外,收集器还将包装函数添加到其他系统库调用中,以保证性能数据的完整性。如果未预装入库,则不能插入这些包装函数。有关收集器如何插入系统库函数的更多信息,请参见使用系统库

预装入 libcollector.so必须使用环境变量同时设置库的名称和库的路径,如下表中所示。使用环境变量 LD_PRELOAD 设置库的名称。使用环境变量 LD_LIBRARY_PATHLD_LIBRARY_PATH_32LD_LIBRARY_PATH_64 设置库的路径。如果未定义 _32_64 变量,则使用 LD_LIBRARY_PATH。如果已经定义了这些环境变量,则向其中添加新值。

表 3–2 用来预装入 libcollector.soer_sync.soer_heap.so 的环境变量设置

环境变量 

值 

LD_PRELOAD

libcollector.so

LD_PRELOAD

er_heap.so

LD_PRELOAD

er_sync.so

LD_LIBRARY_PATH

/opt/solstudio12.2/prod/lib/dbxruntime

LD_LIBRARY_PATH_32

/opt/solstudio12.2/prod/lib/dbxruntime

LD_LIBRARY_PATH_64

/opt/solstudio12.2/prod/lib/v9/dbxruntime

LD_LIBRARY_PATH_64

/opt/solstudio12.2/prod/lib/amd64/dbxruntime

如果 Oracle Solaris Studio 软件未安装在 /opt/solstudio12.2 中,请向系统管理员咨询正确的路径。可以在 LD_PRELOAD 中设置全路径,但是,当使用 SPARC V9 64 位体系结构时,这样做会使问题复杂化。


注 –

运行后删除 LD_PRELOADLD_LIBRARY_PATH 设置,以便它们对于从同一个 shell 启动的其他程序无效。


从 MPI 程序收集数据

该收集器可以从使用消息传递接口 (Message Passing Interface, MPI) 的多进程程序收集性能数据。

该收集器支持 Oracle Message Passing Toolkit 8(以前称为 Sun HPC ClusterTools 8)及其更新。该收集器可以识别其他版本的 MPI;当您运行不带参数的 collect 时,将显示有效的 MPI 版本列表。

http://www.oracle.com/us/products/tools/message-passing-toolkit-070499.html 中提供了 Oracle Message Passing Toolkit MPI 软件。

有关 MPI 和 MPI 标准的信息,请参见 MPI Web 站点 http://www.mcs.anl.gov/mpi/。有关 Open MPI 的更多信息,请参见 Web 站点 http://www.open-mpi.org/

要从 MPI 作业收集数据,必须使用 collect 命令;dbx collector 子命令不能用于启动 MPI 数据收集。对 MPI 运行 collect 命令中提供了详细信息。

对 MPI 运行 collect 命令

collect 命令可用于跟踪和分析 MPI 应用程序。

要收集数据,请使用以下语法:


collect [collect-arguments] mpirun [mpirun-arguments] -- program-name [program-arguments]

例如,以下命令对 16 个 MPI 进程的每个进程运行 MPI 跟踪和分析,在单个 MPI 实验中存储数据:


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

-M OMPT 选项指明将进行 MPI 分析,Oracle Message Passing Toolkit 为 MPI 版本。

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

紧接在 program_name 前面的 -- 参数是 MPI 分析所必需的。如果不包括 -- 参数,collect 命令将显示一条错误消息且不会收集实验。


注 –

不再支持使用 mpirun 命令在 MPI 进程上产生显式 collect 命令的技术来收集 MPI 跟踪数据。您仍可以使用这种技术来收集其他类型的数据。


存储 MPI 实验

由于多进程环境比较复杂,因此从 MPI 程序收集性能数据时应当注意一些有关存储 MPI 实验的问题。这些问题涉及到数据收集和存储的效率以及实验的命名。有关命名实验(包括 MPI 实验)的信息,请参见数据的存储位置

用来收集性能数据的每个 MPI 进程都创建其自己的子实验。当 MPI 进程创建实验时,将锁定实验目录;所有其他 MPI 进程必须一直等待,直到解除锁定,这些进程才可以使用该目录。将试验存储在所有 MPI 进程可以访问的文件系统上。

如果未指定实验名称,则使用缺省的实验名称。在实验中,收集器将为每个 MPI 等级创建一个子实验。收集器使用 MPI 等级以格式 M_rm.er 构造子实验名称,其中 m 是 MPI 等级。

如果打算在实验完成后将其移动到其他位置,则使用 collect 命令指定 -A copy 选项。要复制或移动实验,请勿使用 UNIX® cpmv 命令;而是使用 er_cper_mv 命令,如第 8 章中所述。

MPI 跟踪在每个节点的 /tmp/a.*.z 中创建临时文件。MPI_finalize() 函数调用期间将删除这些文件。确保文件系统有足够的空间用于实验。对长时间运行的 MPI 应用程序收集数据之前,执行短期试运行以确认文件大小。有关如何估计所需空间的信息,另请参见估计存储要求

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

环境变量 VT_BUFFER_SIZE 的缺省值将 MPI API 跟踪收集器的内部缓冲区限制为 64 MB。某一 MPI 进程达到限制的大小时,缓冲区将刷新到磁盘,前提是尚未达到 VT_MAX_FLUSHES 限制。缺省情况下,将 VT_MAX_FLUSHES 设置为 0。该设置将导致 MPI API 跟踪收集器在缓冲区已满时刷新磁盘的缓冲区。如果将 VT_MAX_FLUSHES 设置为正数,就是对允许刷新的次数进行了限制。如果缓冲区已满且无法刷新,不再将该进程的事件写入跟踪文件。结果是试验可能不完整,在某些情况下,实验可能不可读。

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

另一个重要的变量是 VT_VERBOSE,该变量可记录各种错误和状态消息。如果出现问题,请将此变量设置为 2 或更大的值。

通常,当 mpirun 目标存在时,MPI 跟踪输出数据是后处理的;将处理的数据文件写入实验,而将关于后处理时间的信息写入实验标题。如果利用 -m off 显式禁用 MPI 跟踪,就不执行 MPI 后处理。后处理失败时,报告错误,且任何 MPI 标签或 MPI 跟踪度量都不可用。

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

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


注 –

除非您能够访问源文件或者拥有具备相同时间戳的副本,否则在计算机或节点间复制或移动实验时不能在带注释的反汇编代码中查看带注释的源代码或源代码行。可以在当前目录中放置指向原始源文件的符号链接,以便查看带注释的源代码。也可以使用“设置数据显示”对话框中的设置:通过“搜索路径”标签(请参见“搜索路径”标签),您可以管理要用来搜索源文件的目录列表;通过“路径映射”标签(请参见“路径映射”标签),您可以将文件路径的前面部分从一个位置映射到另一个位置。


从脚本收集数据

缺省情况下,collect 要求其目标为 ELF 可执行文件并检查目标以对这一点进行确认。但是,您可以禁用此检查并启用 collect 使其针对指定为目标的脚本运行。


注 –

将脚本分析视为一项实验功能。其实现方式在后续发行版中可能有变化。


要分析脚本,需要首先设置环境变量 SP_COLLECTOR_SKIP_CHECKEXEC 以禁用对 ELF 可执行文件的检查。

缺省情况下,针对为执行脚本而启动的程序和所有子孙进程收集数据。要仅针对特定进程收集数据,请使用 -F 标志指定要跟踪的可执行文件的名称。例如,要分析脚本 foo.sh,但是首先从可执行文件 bar 收集数据,需要使用以下命令。

对于 csh


% setenv SP_COLLECTOR_SKIP_CHECKEXEC 
% collect -F =bar foo.sh

对于 sh


$ export SP_COLLECTOR_SKIP_CHECKEXEC
$ collect -F =bar foo.sh

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

collectppgsz 一起使用

通过在 ppgsz 命令上运行 collect 并指定 -F on-F all 标志,可以将 collectppgsz(1) 一起使用。创始实验位于 ppgsz 可执行文件上,我们不需要关注它。如果您的路径找到 32 位版本的 ppgsz,并且实验在支持 64 位进程的系统上运行,则首先要做的是针对它的 64 位版本执行 exec,创建 _x1.er。该可执行文件将进行派生,创建 _x1_f1.er

子进程尝试针对路径上的第一个目录中指定的目标执行 exec,然后针对第二个目录中的目标执行 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,那么,针对实际目标执行 exec 操作的派生子进程的数据位于 _f1.er 中,而实际目标的实验位于 _f1_x3.er 中,前提是采用与上例相同的路径属性。