本章介绍如何测量和显示程序性能。了解程序计算周期中最耗时的地方及其系统资源使用效率是性能调节的先决条件。
开发高性能应用程序需要综合运用编译器功能、优化例程库以及性能分析工具。
Sun Studio 软件提供了一对用于收集和分析程序性能数据的高级工具:
收集器按称为剖析的统计方式收集性能数据。这些数据包括调用栈、微观统计信息、线程同步延迟数据、硬件计数器上溢数据、地址空间数据以及操作系统的汇总信息。
性能分析器用于显示收集器记录的数据,从而可以检查相应信息。分析器处理数据,并在程序、函数、调用者-被调用者、源码行和反汇编指令级别显示性能的各种度量。这些度量分为三组:基于时钟的度量、同步延迟度量和硬件计数器度量。
性能分析器还可通过创建映射文件(可以使用该映射文件来改进函数在应用程序地址空间中的装入顺序)来协助优化应用程序性能。
这两个工具有助于回答以下各种问题:
程序消耗的可用资源有多少?
最消耗资源的是哪些函数或负载对象?
哪些源码行和反汇编指令耗用的资源最多?
程序在执行过程中如何出现这种问题?
函数或负载对象消耗的是哪些资源?
性能分析器主窗口显示程序函数列表,其中有每个函数的互斥及相容度量。可以用加载对象、线程、轻量进程 (LWP) 和时间片来过滤此列表。对于选中的函数,辅助窗口会显示此函数的调用者和被调用者。有些情况下(例如,搜索高度量值时),可以使用该窗口在调用树中进行导航。另两个窗口显示源代码和反汇编代码,源代码以性能度量逐行进行注解并与编译器注释穿插在一起,反汇编代码以每条指令的度量进行注解。如果可用,源代码和编译器注释将与这些指令穿插在一起。
收集器和分析器适用于所有软件开发人员,尽管性能优化并不是开发人员的主要职责。与常用剖析工具 prof 和 gprof 相比,它们提供了更加灵活、详细和准确的分析,并且不会受 gprof 中属性错误的影响。
收集器和分析器均有等效的命令行方式:
可以使用 collect(1) 命令收集数据。
可以从 dbx 中使用 collector 子命令运行收集器。
命令行实用程序 er_print(1) 可输出 ASCII 形式的各种分析器显示信息。
命令行实用程序 er_src(1) 可显示标注了编译器注释的源代码与反汇编代码列表,但不包含性能数据。
有关详细信息,请参见 Sun Studio《Program Performance Analysis Tools》手册。
收集有关程序性能和资源利用情况的基础数据的简单方法是使用 time (1) 命令或 set time 命令(在 csh 中)。
使用 time 命令运行程序会在程序终止时打印一行计时信息。
demo% time myprog The Answer is: 543.01 6.5u 17.1s 1:16 31% 11+21k 354+210io 135pf+0w demo% |
以下是解释:
user system wallclock resources memory I/O paging
6.5u 17.1s 1:16 31% 11+21k 354+210io 135pf+0w |
system-系统代码中该任务约 17.1 秒
wallclock-完成时间 1 分 16 秒
resources-该程序占用了系统资源的 31%
memory-共享程序内存为 11 KB,专用数据内存为 21 KB
I/O-读取 354 次,写入 210 次
paging-缺页 135 次,换出 0 次
在多处理器环境中以并行方式运行程序时,计时结果的解释方法不同。由于 /bin/time 会累加不同线程上的用户时间,因此只使用挂钟时间。
由于所显示的用户时间包括花费在所有处理器上的时间,因此该值可以相当大,用于测量性能并不很好。最好是进行实时测量,即用挂钟时间。这也意味着要获得并行程序的精确计时,必须在只供您程序使用的闲适系统中运行它。
tcov(1) 命令用于使用 -xprofile=tcov 选项编译的程序时,会生成源代码的逐句剖析信息,显示执行了哪些语句以及执行频率。它还会给出有关程序基本块结构的信息摘要。
增强的语句级覆盖范围通过 -xprofile=tcov 编译器选项和 tcov -x 选项调用。输出源文件的副本,并在页边空白处注以语句执行计数。
如果编译器内联了例程调用,则 tcov 生成的代码覆盖范围报告不可靠。无论何时,只要合适,编译器均会以 -O3 以上的优化级别并根据 -inline 选项内联调用。有内联发生时,编译器会用被调用例程的实际代码替换例程的调用。而且,由于无任何调用,因此 tcov 不会报告对这些内联例程的引用。因此,要获得精确的覆盖报告,请不要启用编译器内联。
要使用 tcov,请使用 -xprofile=tcov 进行编译。运行程序时,覆盖范围数据存储在 program.profile/tcovd 中,其中 program 是可执行文件的名称。(如果可执行文件是 a.out,则会创建 a.out.profile/tcovd。)
可运行 tcov -x dirname source_files 创建与每个源文件合并在一起的覆盖范围分析。相应的报告写入当前目录中的 file.tcov。
运行一个简单示例:
demo% f95 -o onetwo -xprofile=tcov one.f two.f demo% onetwo ... output from program demo% tcov -x onetwo.profile one.f two.f demo% cat one.f.tcov two.f.tcov program one 1 -> do i=1,10 10 -> call two(i) end do 1 -> end .....etc demo% |
环境变量 $SUN_PROFDATA 和 $SUN_PROFDATA_DIR 可以用于指定中间数据收集文件的保存位置。这些文件是由旧式和新式 tcov 分别创建的 *.d 和 tcovd 文件。
这些环境变量可以用来分离来自不同次运行的收集数据。设置了这些变量后,运行程序便会将执行数据写入 $SUN_PROFDATA_DIR/$SUN_PROFDATA/ 中的文件。
同样,tcov 读取的目录也通过 tcov -x $SUN_PROFDATA 指定。如果设置了 $SUN_PROFDATA_DIR,tcov 会对其进行预置,从而在 $SUN_PROFDATA_DIR/$SUN_PROFDATA/ 中查找文件,而不是在工作目录中查找。
随后的每次运行都会将更多的覆盖范围数据累加到 tcovd 文件中。当程序在相应源文件重新编译后首次执行时,会将每个目标文件的数据全部清零。删除 tcovd 文件会将整个程序的数据全部清零。
有关详细信息,参见 tcov(1) 手册页。