原文参考
ARM性能分析器(Streamline) 7.0版开始支持基于SPE(统计性能分析扩展)的性能分析。SPE是Armv8.2-A架构中的一个可选扩展特性,它可以以很低的代价对处理器的流水线进行采样。Streamline可以从Arm Development Studio和Arm Mobile Stuido获取。
为什么需要SPE?
Streamline前序版本只能通过硬件计数器和软中断中采样PC信息获取CPU的信息。硬件计数器只记录触发事件加总数,不可能知道具体哪条指令触发了事件,它只能大致提供应用程序哪块代码触发了这个计数器增加,而往往这块代码区域都比较大,这也导致了能通过这个信息来确定问题的开发者有限。同时因为采样和解析都是通过中断中的软件来完成的,这也导致了程序计数器和栈的采样率也是有限,太高的频率会导致增大系统负载。SPE通过利用CPU流水线中的硬件对PC值进行周期性采样来避免前面提到的问题,因此采样率可以很高,并且没有性能负担。因为SPE是构建在处理器流水线里面,它可以直接采集每条指令相关的附加信息,这方便我们进一步分析执行代码。
工具支持
Streamline支持同时收集系统/应用模式下的SPE数据和其他性能计数器数据。它支持图形化显示下列SPE数据:
事件包可以用来识别分支预测,糟糕的缓存试用,锁竞争等问题。
这些数据可以通过时间线显示这些事件发生的顺序,也可以在函数调用路径,代码试图中看到。这让用户可以追踪到线程,函数,代码行和指令行。
先决条件
使用SPE需要硬件支持相应的扩展,内核需要使能arm_spe_pmu,设备树或者UEFI需要支持SPE。此外,SPE目前需要KPTI失效(启动kernel的时候设置kpti=off),这个要求在Arm后续处理器上可能不需要。可以通过检查是否存在/sys/bus/events/devices/arm_spe_0文件验证内核是否支持SPE。检查dmesg的输出是否有
Kernel/User page tables isolation: enabled
或者查看/sys/devices/system/cpu/vulnerabilities/meltdown是否包含Mitigation: PTI if enabled.
为了使用SPE,你需要有一个支持SPE的设备,或者使用arm的虚拟平台FVP。本文使用Arm Neoverse N1 SDP。如果你想在虚拟平台上测试,你可以使用FVP_Base_RevC-2xAEMv8A。Arm Mobile Studio支持SPE,但是目前还没有消费级的Android设备支持SPE,本文重点使用Arm Development Studio中的Streamline进行演示。
Neoverse N1 SDP配置本文使用Arm Neoverse N1 Software Development Platform运行一个基于Linux 5.4.1内核的环境。除了需要使能Streamline需要的内核选项和前面的提到的内核选项,不需要其他特殊配置。Neoverse N1 SDP 是一款针对服务器市场的开发平台,目前尚未公开,只有早期客户才能获取。该平台内含一颗Neoverse N1处理器,第一个支持SPE的处理器。
FVP配置
如果你希望在arm虚拟平台上尝试SPE功能,可以通过下面参数使能SPE : -C cluster0.has_armv8-2=1 -C cluster0.has_statistical_profiling=1 -C cluster1.has_armv8-2=1 -C cluster1.has_statistical_profiling=1因为FVP并不包含时序信息,所有的指令周期都只需要一个cycle,所以在FVP上的延迟计数器包中显示延迟都是0.同时FVP也不模拟分支预测,所以所有的分支预测都显示正确。缓存模型可以被使能,使能后,SPE可以显示缓存模型行为的相关事件。
开工
在设备上Gatord需要用root启动。Arm Development Studio用户可以通过下面命令进行全系统分析。
/path/to/gatord
也可以通过下面的命令对某个应用进行分析
/path/to/gatord --system-wide no --app <some-app-to-launch>
启动Streamline,连上设备,从计数器配置窗口可以看到Arm SPE(Statistical Profiling Extension)配置界面
Figure 1 SPE配置对话框
这个对话框可以让用户基于操作类型,事件,最小延迟过滤出感兴趣的事件。所有的操作默认都会被采样,但也可以只采样某种分支,存取操作的组合。相似的,也可以只采样一些事件来进一步降低采样量。过滤设置可以针对某类问题降低采集的数据量。比如最低总延迟可以用来提取除缓存外的内存操作。错误预测事件可以用来寻找那些触发错误的程序分支。尽管硬件允许,Streamline目前并不能让用来设置采样率。目前采样率是每100000指令采样一次。Streamline下一个版本,7.2,会支持配置采样率。
Note: SPE运行时每隔n个指令进行一次采样,看其是否满足filter条件再送给Streamline后台,而不是过滤所有样本后每隔n条指令进行采样。当Streamline采集数据到本地文件时,--spe选项参数可以用来控制SPE采样配置。
检查数据
下图显示添加了更多SPE计数器的时间图。SPE事件包内的多种属性显示再堆叠图上。这些图显示了某种属性在样本中存在和不存在的比例。白色方块中显示再所选事件内包含某种属性样本的总和。有些属性和某些特定类型的指令相关,比如分支,存取。比如Architecturally retired图显示了采样的指令最后完成了和没有完成的数量,总量显示了冒险执行的总指令量。类似地, Level 1 Data Cache Access图显示了采样指令中含有对L1数据缓存存取指令总数,以及hit/miss比例。Note:这些图标不会实时显示,经过离线分析后会显示。这些事件图显示了被采样进程的行为概述,可以用来进一步通过分析试图来分析感兴趣区域的细节。分析视图中默认显示采集过程中每个计数器和事件发生次数总和。当你发现感兴趣区域,卡尺工具可以用来再分析视图中过滤出感兴趣区域的数据。
Figure 2使用cross-section标记选择感兴趣区域,本图显示一个对L2缓存利用率不足的benchmark的SPE计数器,采样模板使用实验性N1 SPE模板
进一步分析Streamline有很多视图用来进一步分析理解被分析对象的行为。这包括调用路径栏,函数视图栏和代码栏。
调用路径栏调用路径视图显示了按照进程和线程显示的调用栈。因为SPE只是采样PC而不是调用栈,每个进程中的函数只是平铺展开。默认情况,本视图只显示传统的周期性采样数据,为了显示SPE数据,从下拉菜单中选择SPE。
Figure 3下拉菜单显示调用栈
事件包显示了每个函数中符合条件和不符合条件的采样比例,以及每个线程和进程中事件的加总数。通过点击第一列的表,可以将这些比例单独成列用来排序,这些独立的列显示了符合条件的事件量,以及占总量的比例。通过对这些列的排序,可以确定哪些函数导致缓存存取失败,或哪些函数导致分支预测失败率最高。
Figure 4 可配置显示列
Figure 5基于L1数据缓存存取失败排序的函数
延迟计数器以Log2(Latency)为横轴的直方图显示,列按照0延迟,1 cycle延迟,2-3 cycles延迟,4-7 cycles延迟,8-15 cycles延迟等等,直至采集到的最大延迟。
Figure 6 可能的延迟例子,深色的部分显示所有延迟中的高延迟部分,一行中的高一些的柱图显示一行中的高延迟
调用路径视图的下半部分显示子视图。对于周期性的调用栈采样,它会用来显示某个选择的函数下的所有函数调用占所有采样中的比例。但是SPE数据只会将进程/线程中的函数平铺展开,这里只会显示进程/线程中函数占用父进程/线程中调用比例(A函数在子线程/进程中被调用次数除以A函数在父子进程中调用次数)。
Figure 7调用路径子视图,显示一个线程的所有函数
函数栏函数视图栏显示了所有进程的中函数列表。和调用路径栏一样,函数栏也有一个下拉菜单选择显示数据。类似地,每个列也可以通过点击头部添加删除。
Figure 8函数栏,显示L1数据缓存存取失败的SPE数据
代码栏点击代码栏或者在调用路径视图,函数栏中右键选择一个函数即刻看到相关代码栏。和前面二种视图有所不同,本视图一次只显示一列。你可以从下拉菜单中进行相应选择配置视图。
Figure 9使用下拉菜单选择代码视图配置
反汇编显示基于每条指令的计数器变化,比如可以显示每条指令的延迟。
Figure 10反汇编视图
如果分析的程序包含调试信息,视图还会显示代码行信息,如果运行Streamline的机器上关联了被调试程序的源码,代码栏的上半部分会显示被选择函数的源码,同时每行代码运行带来的计数器变化也会显示。这可以用来识别函数中需要特别处理代码块。
Figure 11源码视图,和图10中显示同样延迟
下一步将Arm Development Studio升级到2019.1/2019.b版本,开始使用Streamline中的SPE功能。了解更多关于Neoverse N1和相关参考平台的信息,请参考我们的通告。