“运行监视器”分析信息使用 Oracle Developer Studio 性能分析工具以及底层操作系统进行收集。“运行监视器”工具以图形方式显示信息,其中包含一些按钮,单击这些按钮可以显示有关代码中问题区域的更多信息。本节将设置一个分析演示项目,在项目的属性中启用分析工具并检查“运行监视器”分析工具的结果。
本教程将使用 ProfilingDemo 样例项目。创建此演示:
选择 "File"(文件)> "New Project"(新建项目)(Ctrl+Shift+N)。
在 "New Project"(新建项目)向导中,展开 "Samples"(样例)节点,然后选择 "C/C++" 类别。
选择分析演示项目。单击 "Next"(下一步),然后单击 "Finish"(完成)。
配置项目并启用分析:
右键单击 "Projects"(项目)标签中的 "ProfilingDemo_1" 项目节点,然后选择 "Properties"(属性)。
选择 "Categories"(类别)面板中的 "Build"(生成)节点,并确保 "Tool Collection"(工具集合)设置为 "Oracle Developer Studio"。
选择 "Categories"(类别)面板中的 "Run"(运行)节点,并确保 "Console Type"(控制台类型)设置为 "Internal Terminal"(内部终端)。这样,就可以在 IDE 的 "Output"(输出)窗口而不是外部终端窗口中查看程序输出。
选择 "Categories"(类别)面板中的 "Profile"(分析)节点。注意选中了 "Show profiling indicators during run"(在运行过程中显示分析指示器)选项。可以在任何项目中选中此选项以显示 "Run Monitor Tools"(运行监视器工具)标签。
在 "Profile Configuration"(分析配置)中,选择 "C/C++ Oracle Developer Studio Standard"(C/C++ Oracle Developer Studio 标准)。单击 "Profile Configuration"(分析配置)列表旁边的 "..." 按钮。
请注意,为 "C/C++ Oracle Developer Studio Standard"(C/C++ Oracle Solaris Studio 标准)选择的工具包括 "Thread Usage"(线程使用情况)、"Memory Usage"(内存使用情况)和 "CPU Usage"(CPU 使用情况)。
在 "Project Properties"(项目属性)对话框中单击 "OK"(确定)。
生成并运行 ProfilingDemo_1:
右键单击 ProfilingDemo_1 项目节点,然后选择 "Build"(生成)。
"Output"(输出)窗口显示生成的结果。
右键单击 ProfilingDemo_1 项目节点,然后选择 "Run"(运行)。"Run Monitor"(运行监视器)窗口打开,显示带有动态图形的 "CPU Usage"(CPU 使用情况)、"Memory Usage"(内存使用情况)和 "Thread Usage"(线程使用情况)指示器。
请注意,在输出窗口中,ProfilingDemo_1 程序将显示正在执行的操作,这样您就可以将其与 IDE 在工具中以图形表示的数据进行比较。例如,程序会显示其分配了多少内存,并且还会执行计算,然后释放内存。您可以看到该图反映了此活动。
在每次出现提示时按 Enter 键,直至程序完成。
将鼠标光标悬停在指示器上,以查看解释每个图形所表示内容的工具提示。每个指示器包含一个用于显示更详细信息的按钮,将在后面部分介绍该按钮。
在 "Run Monitor"(运行监视器)窗口底部,可以看到用于控制图形视图的滑块:视图滑块、详细信息滑块和时间滑块。这些控件还用于过滤数据。下图标记了这些控件。
将鼠标光标放在滑块端点上以显示滑块的相关信息。
在时间滑块(底部的水平滚动条)上单击并按住鼠标按钮。所有图形将一致地滑动,这样,您可以看到任何给定时间的 CPU、内存和线程,并可以查看它们之间的关系。
从左向右拖动时间滑块以查看完整运行情况。
将鼠标移到视图滑块(与时间单位重叠的控件)。视图滑块控制在指示器中显示的运行时间部分。
单击视图滑块起点的手柄并将其拖动到运行开始部分。指示器显示整个运行情况。效果与缩小操作类似。请注意,选择完整运行时间时会将时间滚动条最大化,因为您已经在查看所有数据。
将视图滑块的起点拖到 PTHREAD_MUTEX_DEMO 开始的位置。在拖动手柄时,指示器将放大以聚焦到此区域。请注意,可以重新使用滚动条在运行时间中滚动。
将鼠标光标放在橙色详细信息滑块终点上,以显示如何使用滑块的说明。通过使用详细信息滑块控件,可以选择某个运行时部分以查看详细信息。
将详细信息滑块的起点手柄拖过视图滑块的起点。请注意,指示器将详细信息滑块起点前面的区域灰显。这样,便可突出显示起点和终点之间的图形。单击指示器的详细信息按钮时,详细信息标签将显示突出显示的区域的数据。
将详细信息滑块的起点拖回到开始处,这样可以看到所有数据。
"CPU Usage"(CPU 使用情况)图显示了应用程序在其运行期间所使用的 CPU 总时间的百分比。
单击 "CPU Usage"(CPU 使用情况)中的 "Hot Spots..."(热点...)按钮以显示有关 CPU 时间的详细信息。
"CPU Time Per Function"(每个函数的 CPU 时间)窗口会打开,显示程序的各个函数以及每个函数所使用的 CPU 时间。这些函数按照使用的 CPU 时间顺序列出,使用时间最多的函数将列在最前面。如果程序仍在运行,最初显示的时间是单击图形时所用的时间。
单击 "Function Name"(函数名)列标题以按字母顺序对函数进行排序。
请注意两列 "CPU Time"(CPU 时间)之间的差异。"CPU Time (Inclusive)"(CPU 时间(包含))显示从进入函数的时间起直到函数退出的时间为止所花费的 CPU 总时间,包括所列函数调用的所有其他函数的时间。"CPU Time (Exclusive)"(CPU 时间(独占))显示特定函数(不包括它所调用的任何函数)专用的时间。
单击 "CPU Time (Inclusive)"(CPU 时间(包含))列标题可将用时最多的函数放回到顶部。
请注意,在我们的示例中,work_run_usrcpu() 函数的 "CPU Time (Exclusive)"(CPU 时间(独占))为 613.079,而 "CPU Time (Inclusive)"(CPU 时间(包含)) 为 613.499。这意味着 work_run_usrcpu() 函数调用的其他函数实际使用了少量的 CPU 时间,而其自身使用了大部分时间。
一些函数以粗体列出。可以转至调用这些函数的源文件。双击 work_run_usrcpu() 函数。
将会打开 common.c 文件,并且光标停留在第 60 行的 work_run_usrcpu() 函数上。此行的左边界中显示一些数字。
将光标悬停左边界中的数字上。这些数字是与 "CPU Time Per Function"(每个函数的 CPU 时间)窗口中所显示函数的独占和包含 CPU 时间相同的度量。这些度量四舍五入到了小数点后一位,但将鼠标悬停在这些数字上时将弹出未四舍五入前的值。common.c() 源文件中也会显示 CPU 消耗行的度量(例如在 work_run_usrcpu() 函数内执行计算的 for 循环)。
在 "CPU Time Per Function"(每个函数的 CPU 时间)窗口中,通过键入时间并按 Enter 键,或者使用箭头滚动选择秒数,将 "Time Filter"(时间过滤器)开始时间更改为 0:40。图形指示器将发生变化,如同在数据过滤控件上移动手柄时一样。如果拖动手柄,将更新 "CPU Time Per Function"(每个函数的 CPU 时间)窗口中的 "Time Filter"(时间过滤器)设置以保持一致。更重要的是,将更新为表中的函数显示的数据以反映过滤器设置,以便仅显示在该时间段内使用的 CPU 时间。
也可以进行过滤以仅显示满足特定度量的数据。右键单击 work_run_usrcpu() 的 "CPU Time (Exclusive)"(CPU 时间(独占))度量。在我们的示例中,右键单击 "CPU Time Per Function"(每个函数的 CPU 时间)窗口中的 43.07。选择 "Show only where > CPU Time (Exclusive) == 43.07"(仅显示 CPU 时间(独占)等于 43.07 的行)。此时将过滤所有行,并仅显示其独占 CPU 时间等于 43.07 的行。
"Memory Usage"(内存使用情况)指示器显示了项目的内存堆在其运行时如何变化。您可以使用该工具来识别内存泄漏,内存泄漏是指程序中不再需要的内存无法释放的点。内存泄漏可能会导致程序中的内存消耗增加。如果某个存在内存泄漏的程序运行足够长的时间,它最终可能会用尽可用内存。
在 "Run Monitor"(运行监视器)中左右滑动滑块,以查看内存堆如何随时间增加或减少。ProfilingDemo_1 中应该出现四次使用峰值。前两次出现在串行演示期间,第三次出现在并行演示期间,最后一次出现在 Pthread 互斥演示期间。
单击 "Memory Leaks"(内存泄漏)按钮显示 "Memory Leak Details"(内存泄漏详细信息)窗口。这将显示有关哪些函数呈现内存泄漏的详细信息。出现的表中只会列出产生内存泄漏的函数。如果单击该按钮时程序正在运行,显示的泄漏位置就是单击按钮那一刻存在的位置。随着时间的推移,可能会发生更多泄漏,因此,应单击 "Refresh"(刷新)按钮。如果直到运行结束仍未检测到任何内存泄漏,"Memory Leak Details"(内存泄漏详细信息)标签会指示未找到内存泄漏。
可以更改 "Start"(开始)和 "End"(结束)时间来过滤数据,或使用 "Run Monitor"(运行监视器)窗口中的橙色详细信息滑块(与“了解 CPU 使用情况”一节中相同)。本示例中没有内存泄漏。
双击某个函数,将打开相应文件并停在函数中发生内存泄漏的行。源代码编辑器的左边界中将显示内存泄漏度量。
将鼠标移到度量上以显示详细信息,如同对 CPU 使用情况度量执行的操作一样。
右键单击表中的度量以过滤表中的数据。此表中数据过滤功能在所有分析工具中均可用。
"Thread Usage"(线程使用情况)指示器显示了程序正在使用的线程数量以及线程必须等待锁以继续执行其任务的时间。此数据对于多线程应用程序很有用,这些应用程序为了避免昂贵的等待时间必须执行线程同步。
"Thread Usage"(线程使用情况)指示器显示项目运行时所运行的线程数。将时间滑块滑回开始处,注意线程数为 1,直到并行演示开始。在下图中,该时间为 8:07,从 1 个线程跳跃到 32 个。
将视图滑块端点手柄移至并行演示刚刚开始的位置。
请注意,在同一时间段的 "CPU Usage"(CPU 使用情况)和 "Memory Usage"(内存使用情况)指示器中,单个线程正在执行某个使用 CPU 时间和内存的活动。此时间段对应于串行演示部分,主线程先在文件中写入数据,然后再执行一些计算。在程序等待用户按 Enter 键时,CPU 和内存使用率将会减少,线程数保持为 1 个。
向右滑动时间滑块,直到看到线程数增加的两个点。
8:07 时的线程数增加与项目运行的并行演示部分相对应。主线程启动其他线程,执行向文件写入的工作以及并行执行计算。请注意内存使用情况和 CPU 使用情况的增加,但是完成两个任务的时间要少得多。
在并行演示线程结束后,线程数恢复为 1 个,主线程等待您按 Enter 键。运行程序的 Pthread 互斥演示部分时,线程数将再次增加。
请注意,在 Pthread 互斥演示部分出现锁等待,以橙色显示。Pthread 互斥演示使用互斥锁来防止多个线程对某些函数进行重叠访问,这会导致线程需要等待获取锁。
单击 "Sync Problems"(同步问题)按钮以显示有关项目中的线程锁定的详细信息。将打开 "Thread Synchronization Details"(线程同步详细信息)窗口,并列出必须等待获取互斥锁的函数。还会显示以下度量:函数等待时所花费的毫秒数以及函数必须等待获得锁的次数。本示例没有同步问题。
如果在程序运行时单击 "Sync Problems"(同步问题)按钮,则可能需要单击刷新按钮 ,以使用最新线程锁定信息更新显示。
单击 "Wait Time"(等待时间)列以按等待所花费的时间顺序对函数进行排序。
单击 "Lock Waits"(锁等待次数)列以按函数中线程等待的次数对函数进行排序。
双击某个函数以便在编辑器中打开其源文件并停在该函数负责锁定内存位置的位置。"Wait Time"(等待时间)和 "Lock Waits"(锁等待次数)度量显示在源文件的左侧列中。请将鼠标放在度量上以查看详细信息,它与 "Thread Synchronization Details"(线程同步详细信息)窗口中显示的内容是一致的。
右键单击这些度量,并取消选定 "Show Profiler Metrics"(显示分析器度量)。这些度量将不会再显示在任何配置工具的程序编辑器中。要重新显示度量,请在 IDE 菜单栏中选择 "View"(视图),然后选择 "Show Profiler Metrics"(显示分析器度量)。