本节介绍同步跟踪数据并说明如何将其与时钟分析数据相关联。
转至 "Functions"(函数)视图并单击列标题 "Inclusive Total CPU"(包含总 CPU 时间)来根据包含 "Total CPU Time"(总 CPU 时间)进行排序。
选择列表顶部的 do_work() 函数。
查看 "Functions"(函数)视图底部的 "Called-by/Calls"(调用方/调用)面板,并注意从两个位置调用 do_work(),并且其调用十个函数。
通常情况下,创建处理数据的线程时会调用 do_work(),并在从 _lwp_start() 调用时显示它。在一种情况下,从 locktest() 被调用后,do_work() 调用名为 nothreads() 的单线程任务。
do_work() 调用的十个函数表示十个不同任务,每个任务使用程序执行的一个不同的同步方法。在从 mttest 创建的一些实验中,您可能会看到第十一个函数,该函数使用相对较少的时间获取其他任务的工作块。函数 fetch_work() 显示在前面屏幕抓图中的 "Calls"(调用)面板中。
请注意,除了 "Calls"(调用)面板中的前两个被调用方,所有被调用方都显示大约相同的 "Attributed Total CPU"(归属总 CPU)时间量(约为 10.6 秒)。
切换到 "Callers-Callees"(调用方-被调用方)视图。
"Callers-Callees"(调用方-被调用方)视图显示与 "Called-by/Calls"(调用方/调用)面板相同的调用方和被调用方,但是还显示 "Overview"(概述)页面中选择的其他度量,包括 "Attributed Sync Wait Time"(归属同步等待时间)。
查找 lock_global() 和 lock_local() 两个函数,并注意它们显示大约相同的 "Attributed Total CPU"(归属总 CPU)时间量,但是非常不同的 "Attributed Sync Wait Time"(归属同步等待时间)量。
选择 lock_global() 函数并切换到 "Source"(源)视图。
请注意,所有 "Sync Wait"(同步等待)时间都位于包含对 pthread_mutex_lock(&global_lock) 的调用的行上,其 "Total CPU Time"(CPU 总时间)为 0。正如您可以从函数名称猜测到的,执行此任务的四个线程都在获取全局锁时执行其工作,它们逐个获取全局锁。
转回 "Functions"(函数)视图并选择 lock_global(),然后单击 "Filter"(过滤器)图标并选择 "Add Filter: Include only stacks containing the selected functions"(添加过滤器:仅包括含有所选函数的堆栈)。
选择 "Timeline"(时间线)视图,您应该看到四个线程。
获取锁的第一个线程(屏幕抓图中的 T:17)工作 2.65 秒,然后放弃该锁。您可以看到该线程的状态条为绿色,表示其所有时间都花费在 "User CPU Time"(用户 CPU 时间),没有任何时间花费在 "User Lock Time"(用户锁定时间)。还请注意,使用
标记的 "Synchronization Tracing Call Stacks"(同步跟踪调用堆栈)的第二个条未显示此线程的调用堆栈。
第二个线程(屏幕抓图中的 T:16)已经在 "User Lock Time"(用户锁定时间)等待了 2.6 秒,然后计算了 2.65 秒并放弃该锁。"Synchronization Tracing Call Stacks"(同步跟踪调用堆栈)与 "User Lock Time"(用户锁定时间)一致。
第三个线程 (T:15) 已经在 "User Lock Time"(用户锁定时间)等待了 5.3 秒,然后计算了 2.65 秒并放弃该锁。
最后一个线程 (T:14) 已经在 "User Lock Time"(用户锁定时间)等待了 7.9 秒,然后计算了 2.65 秒。总计算时间为 2.65 x 4 或大约 10.6 秒。
总同步等待时间为 2.6 + 5.3 + 7.9 或大约 15.9 秒,可以在 "Function"(函数)视图中确认该值。
通过单击 "Active Filters"(活动过滤器)面板中的 X 来删除过滤器。
转回 "Function"(函数)视图,选择函数 lock_local(),然后切换到 "Source"(源)视图。
请注意,包含对 pthread_mutex_lock(&array->lock) 的调用的行(屏幕抓图中的行 1043)上的 "Sync Wait Time"(同步等待时间)为 0。这是因为锁对于工作块来说是本地的,所以不存在争用,所有四个线程可以同时进行计算。
您查看的实验是使用校准阈值记录的。在下一节中,您将与另一个实验进行比较,您运行 make 命令时使用零阈值记录该实验。