如何运用Visual Studio 图形工具调试和优化基于Unity的混合现实应用?

当我们准备开始调试和优化混合现实应用时,需要Unity导出能够Debug项目:

Unity C# Projects 和 Development Build是必选的:

1. 当我们准备开始调试和优化混合现实应用时,需要Unity导出能够Debug项目:

Unity C# Projects 和 Development Build是必选的:

Unity 2017.2 软件界面

2. 符号表的设置

在调试应用时,配置好符号表可以帮助在研究问题时准确的看到堆栈中函数名称。选择 Debug -> Options -> Debugging -> Symbols 做配置。

Unity的符号表服务器地址是: http://symbolserver.unity3d.com/

微软的符号表服务器地址是自带的,有必要的话,可以自行添加选择更多。

Visual Studio 2017软件界面

注意:通常头几次程序调试时,因为逐个下载符号表文件需要时间,可能到关注的问题点之前,应用就停止运行,多尝试几次到符号表文件下载完成就可以,后面的调试就会快很多。还有一个加快速度的方法就是选择”Load only specified modules”,这样可以避免加载不需要的模块符号表。

符号表文件夹内容是这样的,有很多PDB文件夹。一个项目团队可以共用一个符号表文件服务路径,这样可以减少从外部下载符号表的时间:

符号表位置和样式

异常退出

异常退出也就是我们常提到的程序崩溃。因为Unity 导出成MR项目后,不光有.NET的运行时,一些底层的操作也会涉及到naïve code。为了保证.Net和Native产生的异常都可以抓到,通常需要做以下两件事情:

1. 配置Exception(快捷键:Ctrl + Alt +E)

根据项目具体遇到的情况,Common Language Runtime Exception 指的就是.Net 的异常:

Visual Studio 2017软件界面

2. 选中Solution里面的 “Universal Platform Application“项目节点,右键并点击Properties,在Debug 栏目中,Debugger Type选择Mixed (Managed and Native):

Visual Studio 2017软件界面

拿个一个HoloLens测试项目做例子,我们在做一系列异步操作时候会间断出现崩溃的错误而退出,错误除了c0000005外没有其它详细信息。在做好准备工作后,在项目里,直接在Debug模式下做F5调试:

在异常出现的时候,可以准确的定位出问题的点是在UnityPlayer异步写video时的崩溃,这样可以重点集中在VideoCapture对象的状态是否正确上,比如在写的时候是否有stopvideo的异步操作冲突,从而加快解决问题的速度:

调用栈信息

CPU使用率过高

在关注CPU使用率的场景里,Performance Profiler会提供非常大的帮助。假设已经用Visual Studio 2017打开该项目,选择Debug -> Performance Profiler:

然后选择CPU Usage:

这里如果需要研究的都是.Net逻辑的话,可以使用Debug,Release,Master的版本, 因为.Net Assembly里面包含了符号表信息。如果研究的是Native代码逻辑,项目需要使用Debug版本.

Performance Profile开启后,程序会运行,到CPU问题复现后,可以点击Stop Collection:

然后工具会分析CPU 使用情况:

结果一目了然,还可以用鼠标选取某个区域,看各个函数在CPU使用的百分比:

选取感兴趣的函数,此函数的source code,下一级被调用的函数的CPU状态,也都清晰展现,非常有帮助:

调用函数的CPU状态

FPS 时间线分析

造成FPS异常(太低)的情况较多,比如:Garbage Collection过于频繁,繁重的IO读写,图形渲染和代码效率问题等等。Visual Studio 2017的Performance Profiler的Frame Rate分析主要对普通的WPF, UWP应用有用,但混合现实应用也能帮助我们了解GC和IO的状态:

假设已经用Visual Studio 2017打开该项目 (建议配置选Release 或 Master ),选择Debug -> Performance Profiler:

这次选择Application Timeline, 并启动它:

Performance Profile开启后,程序会运行,运行一段时间后,可以点击Stop Collection,分析结束后可以选择时间段做查看:

需要注意的时,它的FPS数据有时不一定准确(以《Windows 混合现实性能调优之工具实践(上篇)》 提到的Mixed Reality -Windows Device Portal为准),但在GC和文件读取的数据上,信息清晰且易于参考,比如资源文件的读取时间等:

应用图像的渲染分析

Visual Studio 2017的Graphic Diagnostic功能在分析图像渲染,尤其是针对检查过多的DrawCall,特定Frame的耗时突出DrawCall的分析, DrawCall中体现在Pipeline的不同阶段Shader的执行,都很有帮助,同时这个工具也提供更多Direct3D相关的参数供分析参考。

开始操作前,选择Debug -> Options, 对Graphics Diagnostics做配置,这里选择Collect call stacks:

然后我们就可以选择 Debug -> Graphics -> Start Graphics Debugging开始我们的工作 (或者Alt+F5)。在希望分析的时候,点击Capture Frame:

然后就可以点击抓取到的Frame,打开Frame Analyzer:

在Frame Analyzer里面,左下角是Call Stack,告诉我们在某个图像渲染工作下,涉及到的调用逻辑。如果有些模块没有显示函数名,很可能是符号表没有匹配的。要进一步确认,可以右键点击Event Call Stack,选择Symbol Settings, 来配置符号表 (配置方法和本文开始的符号表配置方法相同):

要进一步分析Frame, 要按照提示先停止应用 (从Visual Studio 2017里面):

再点击Quick Analysis:

这样我们就可以看到在显示这个Frame时,涉及到的DrawCall 和时间长短 (柱状图表示):

选择其中一个DrawCall (比如时间花费最长的), Frame Analyzer会自动把我们带到对应的DrawIndexed:

双击DrawIindexed,在Pipeline Stage窗口,就可以清楚的看到这个Frame里面虚拟物体的渲染过程,用到了哪些Shader:

另外,在Render Target的标签页里面,选择某个物体,还可以看到Pixel History:

告诉我们特定像素变化的历史记录,方便开发者跟踪图像渲染逻辑来进行调试:

以上基于四个不同场景,给出基于Windows调试混合现实应用的基本方法和工具,实际能运用的工具其实不止这些,例如第三方的Unity Profiler和Intel Graphics Performance Analyzer也有自己独特的用途。可以看出,混合现实应用的优化和分析是需要结合通用User Mode程序及图像渲染程序共同的特点来进行的。最后,希望这些介绍可以帮助我们的混合现实开发者提高工作效率,写出更精彩的应用。

(文章转载自:微软HoloLens,作者:李向晖)