Oracle® Developer Studio 12.5:性能分析器

退出打印视图

更新时间: 2016 年 6 月
 
 

"Source"(源)、"Disassembly"(反汇编)和 "PCs"(PC) 标签中的特殊行

性能分析器在 "Source"(源)、"Disassembly"(反编译)和 "PCs" (PC) 视图中显示的某些行并不直接对应于代码行、指令行或程序计数器行。以下部分介绍了这些特殊的行。

外联函数

外联函数可以在反馈优化编译期间创建。 在 "Source"(源)视图和 "Disassembly"(反编译)视图中,外联函数显示为特殊的索引行。在 "Source"(源)视图中,在已转换为外联函数的代码块中会显示一条注释。

                   Function binsearchmod inlined from source file ptralias2.c into the 
0.       0 .         58.         if( binsearchmod( asize, &element ) ) {
0.240    0.240       59.             if( key != (element << 1) ) {
0.       0.          60.                 error |= BINSEARCHMODPOSTESTFAILED;
                        <Function: main -- outline code from line 60 [_$o1B60.main]>
0.040    0.040     [ 61]                 break;
0.       0.          62.             }
0.       0.          63.         }

在 "Disassembly"(反编译)视图中,外联函数通常在文件结尾处显示。

                        <Function: main -- outline code from line 85 [_$o1D85.main]>
0.       0.             [ 85] 100001034:  sethi       %hi(0x100000), %i5
0.       0.             [ 86] 100001038:  bset        4, %i3
0.       0.             [ 85] 10000103c:  or          %i5, 1, %l7
0.       0.             [ 85] 100001040:  sllx        %l7, 12, %l5
0.       0.             [ 85] 100001044:  call        printf ! 0x100101300
0.       0.             [ 85] 100001048:  add         %l5, 336, %o0
0.       0.             [ 90] 10000104c:  cmp         %i3, 0
0.       0.             [ 20] 100001050:  ba,a        0x1000010b4
                        <Function: main -- outline code from line 46 [_$o1A46.main]>
0.       0.             [ 46] 100001054:  mov         1, %i3
0.       0.             [ 47] 100001058:  ba          0x100001090
0.       0.             [ 56] 10000105c:  clr         [%i2]
                        <Function: main -- outline code from line 60 [_$o1B60.main]>
0.       0.             [ 60] 100001060:  bset        2, %i3
0.       0.             [ 61] 100001064:  ba          0x10000109c
0.       0.             [ 74] 100001068:  mov         1, %o3

外联函数的名称显示在方括号中,并对外联代码段的有关信息进行编码,这些信息包括从中提取代码的函数名称以及源代码中该段的起始行号。这些改编名称 (mangled name) 可能随发行版的不同而不同。性能分析器提供了函数名称的可读版本。有关更多详细信息,请参阅外联函数

如果在收集应用程序的性能数据时调用了外联函数,则性能分析器会在带注释的反汇编代码中显示一个特殊行,以显示该函数的非独占度量。有关更多详细信息,请参见非独占度量

编译器生成的主体函数

编译器并行化函数中的循环或具有并行化指令的区域时,将会创建初始源代码中不存在的新主体函数。 OpenMP 软件执行概述中介绍了这些函数。

编译器将改编名称分配给主体函数,这些主体函数对并行结构的类型、从中提取结构的函数名称、初始源代码中该结构的起始行号以及并行结构的序列号进行了编码。 这些改编名称 (mangled name) 因微任务化库的发行版而异,但均会取消改编 (demangle) 为更易于理解的名称。

以下示例显示的是一个由编译器生成的典型主体函数,如计算机模式下的函数列表中所示。

7.415      14.860      psec_ -- OMP sections from line 9 [_$s1A9.psec_]
3.873       3.903      craydo_ -- MP doall from line 10 [_$d1A10.craydo_]

在示例中,最先显示的是从中提取结构的函数名称,接着是并行结构的类型,然后是并行结构的行号,最后在方括号中显示的是由编译器生成的主体函数的改编名称 (mangled name)。类似地,在反汇编代码中,也会生成一个特殊索引行。

0.       0.            <Function: psec_ -- OMP sections from line 9 [_$s1A9.psec_]>
0.       7.445         [24]    1d8cc:  save        %sp, -168, %sp
0.       0.            [24]    1d8d0:  ld          [%i0], %g1
0.       0.            [24]    1d8d4:  tst         %i1
0.       0.            <Function: craydo_ -- MP doall from line 10 [_$d1A10.craydo_]>
0.       0.030         [ ?]    197e8:  save        %sp, -128, %sp
0.       0.            [ ?]    197ec:  ld          [%i0 + 20], %i5
0.       0.            [ ?]    197f0:  st          %i1, [%sp + 112]
0.       0.            [ ?]    197f4:  ld          [%i5], %i3

对于 Cray 指令,函数可能与源代码行号不相关。在这样的情况下,会在行号的位置显示 [ ?]。如果索引行显示在带注释的源代码中,则该索引行指示不带行号的指令,如以下示例中所示。

                     9. c$mic  doall shared(a,b,c,n) private(i,j,k)
                  
                   Loop below fused with loop on line 23
                   Loop below not parallelized because autoparallelization 
                     is not enabled
                   Loop below autoparallelized
                   Loop below interchanged with loop on line 12
                   Loop below interchanged with loop on line 12
3.873     3.903         <Function: craydo_ -- MP doall from line 10 [_$d1A10.craydo_],
                      instructions without line numbers>
0.        3.903     10.            do i = 2, n-1

注 -  在实际显示中,索引行和编译器注释行并不换行。

动态编译的函数

动态编译的函数是指程序执行时编译和链接的函数。 收集器中并没有有关用 C 或 C++ 编写的动态编译函数的信息,除非用户使用收集器 API 函数 collector_func_load() 提供所需的信息。由 "Function"(函数)视图、"Source"(源)视图和 "Disassembly"(反汇编)视图显示的信息取决于传递给 collector_func_load() 的信息,如下所示:

  • 如果未提供信息,则不会调用 collector_func_load()。在函数列表中,动态编译和装入的函数会显示为 <Unknown>。性能分析器中既看不到函数源代码,也看不到反汇编代码。

  • 如果没有提供源文件名和行号表,但提供了函数的名称、大小以及地址,则函数列表中将显示动态编译和装入的函数的名称及度量。带注释的源代码是可用的,并且反汇编指令是可见的,只是行号被指定为 [?],这表示行号未知。

  • 如果提供了源文件名,但未提供行号表,性能分析器显示的信息将与不提供源文件名所显示的信息类似,只是带注释的源代码开头将显示一个特殊索引行,以指示该函数由不带行号的指令组成。 例如:

    1.121     1.121          <Function func0, instructions without line numbers>
                          1. #include        <stdio.h>
  • 如果提供了源文件名和行号表,将按照与常规编译函数相同的方式在 "Function"(函数)视图、"Source"(源)视图和 "Disassembly"(反汇编)视图中显示函数及其度量。

有关收集器 API 函数的更多信息,请参见动态函数和模块

对于 Java 程序,大部分方法由 JVM 软件解释。在解释执行期间,在单独的线程上运行的 Java HotSpot 虚拟机会监视性能。在监视过程中,虚拟机可能决定使用已解释的一个或多个方法,生成相应的计算机代码,并执行更有效的计算机代码版本,而不是解释原始代码。

对于 Java 程序,无需使用收集器 API 函数。性能分析器通过在该方法的索引行下方使用一个特殊行,表明在带注释的反汇编代码列表中存在 JavaHotSpot 编译的代码,如以下示例所示。

                   11.    public int add_int () {
                   12.       int       x = 0;
2.832     2.832      <Function: Routine.add_int: HotSpot-compiled leaf instructions>
0.        0.         [ 12] 00000000: iconst_0
0.        0.         [ 12] 00000001: istore_1

反汇编代码列表仅显示已解释的字节代码,而不显示编译的指令。缺省情况下,在该特殊行的旁边显示已编译代码的度量。该独占和非独占 CPU 时间与各行已解释字节代码的所有独占和非独占 CPU 时间总和不同。通常,如果多次调用该方法,已编译指令的 CPU 时间将大于已解释字节代码的 CPU 时间总和,这种差异之所以出现,是因为已解释代码只是在最初调用该方法时执行一次,而已编译代码则在其后执行。

带注释的源代码不显示 Java HotSpot 编译的函数。而是显示一个特殊索引行,以指示不带行号的指令。例如,下面显示了与上例显示的反汇编提取对应的带注释的源代码:

                     11.    public int add_int () {
2.832     2.832        <Function: Routine.add_int(), instructions without line numbers>
0.        0.         12.       int       x = 0;
                       <Function: Routine.add_int()>

Java 本机函数

本机代码是最初用 C、C++ 或 Fortran 编写,由 Java 代码通过 Java 本地接口 (Java Native Interface, JNI) 调用的已编译代码。 以下示例来自与演示程序 jsynprog 关联的文件 jsynprog.java 的带注释的反汇编代码。

                     5. class jsynprog
                        <Function: jsynprog.<init>()>
0.       5.504          jsynprog.JavaCC() <Java native method>
0.       1.431          jsynprog.JavaCJava(int) <Java native method>
0.       5.684          jsynprog.JavaJavaC(int) <Java native method>
0.       0.             [  5] 00000000: aload_0
0.       0.             [  5] 00000001: invokespecial <init>()
0.       0.             [  5] 00000004: return

由于本机方法不包含在 Java 源代码中,jsynprog.java 的带注释的源代码的开头会显示每个 Java 本机方法,并使用一个特殊的索引行来指示不带行号的指令。

0.       5.504          <Function: jsynprog.JavaCC(), instructions without line 
                           numbers>
0.       1.431          <Function: jsynprog.JavaCJava(int), instructions without line 
                           numbers>
0.       5.684          <Function: jsynprog.JavaJavaC(int), instructions without line 
                           numbers>

注 -  在实际的带注释的源代码显示中,索引行并不换行。

克隆函数

编译器能够识别可以对其执行额外优化的函数调用,例如所传递的部分参数是常量的函数调用。当编译器识别出它可以优化的特定调用时,会创建该函数的副本(称为克隆)并生成优化代码。

在带注释的源代码中,编译器注释将指示是否创建了克隆函数:

0.       0.       Function foo from source file clone.c cloned, 
                   creating cloned function _$c1A.foo; 
                   constant parameters propagated to clone
0.       0.570     27.    foo(100, 50, a, a+50, b);

注 -  在实际的带注释的源代码显示中,编译器注释行并不换行。

克隆函数名称是标识特定调用的改编名称 (mangled name)。在前面的示例中,编译器注释指示克隆的函数名称为 _$c1A.foo。在函数列表中,该函数显示为:

0.350     0.550     foo
0.340     0.570     _$c1A.foo

每个克隆函数都具有不同的指令集,因此带注释的反汇编列表单独显示克隆函数。 这些函数与任何源文件都没有关联,因此其指令也与任何源代码行号无关。以下示例显示了某个克隆函数的带注释的反汇编代码的前几行。

0.       0.           <Function: _$c1A.foo>
0.       0.           [?]    10e98:  save        %sp, -120, %sp
0.       0.           [?]    10e9c:  sethi       %hi(0x10c00), %i4
0.       0.           [?]    10ea0:  mov         100, %i3
0.       0.           [?]    10ea4:  st          %i3, [%i0]
0.       0.           [?]    10ea8:  ldd         [%i4 + 640], %f8

静态函数

静态函数通常在库中使用,因此库内部使用的名称不会与用户可能使用的名称发生冲突。 库被剥离后,静态函数的名称将从符号表中删除。在这样的情况下,性能分析器会为包含剥离静态函数的库中的每个文本区域生成人工名称。该名称的格式为 <static>@0x12345,其中 @ 符号后的字符串是库中文本区域的偏离量。性能分析器无法区分连续的剥离静态函数和单个这样的函数,因此可能出现两个或多个这样的函数,且其度量合并在一起。以下示例显示 jsynprog 样例演示的函数列表中的静态函数。

0.       0.       <static>@0x18780
0.       0.       <static>@0x20cc
0.       0.       <static>@0xc9f0
0.       0.       <static>@0xd1d8
0.       0.       <static>@0xe204

在 "PCs" (PC) 视图中,这些函数使用如下所示的偏移量表示:

0.       0.       <static>@0x18780 + 0x00000818
0.       0.       <static>@0x20cc + 0x0000032C
0.       0.       <static>@0xc9f0 + 0x00000060
0.       0.       <static>@0xd1d8 + 0x00000040
0.       0.       <static>@0xe204 + 0x00000170

在 "PCs" (PC) 视图中,在被剥离的库内调用的函数的替代表示方法为:

<library.so> -- no functions found + 0x0000F870

非独占度量

在带注释的反汇编代码中,有一些特殊的行标记外联函数占用的时间。

以下示例显示了调用外联函数时显示的带注释的反汇编代码:

0.       0.        43.         else
0.       0.        44.         {
0.       0.        45.                 printf("else reached\n");
0.       2.522         <inclusive metrics for outlined functions>

存储和装入指令的注释

利用 –xhwcprof 选项进行编译时,编译器将为存储 (st) 和装入 (ld) 指令生成附加信息。可以在反汇编代码列表中查看带注释的 st ld 指令。

分支目标

使用 –xhwcprof 选项进行编译时,带注释的反汇编代码列表中显示的人工行 <branch target> 与指令的某个 PC 对应,可从多个代码路径到达该指令。