我们重视您的隐私。我们使用cookies来提升您在我们网站的体验。使用本网站即表示您同意我们的隐私政策.

我们如何分析 WebXR/WebGL 应用

我们如何分析 WebXR/WebGL 应用

本文介绍了分析 WebXR 和 WebGL 应用的方法(与底层框架无关)。分析是优化应用的第一步。不进行分析的优化等于浪费精力,正如我们在瓶颈部分所描述的。

请注意,本文并未涉及如何解决发现的性能问题。市面上有很多博客文章和演讲专门针对特定的瓶颈,一旦你知道问题所在,你就能找到解决方案。

我们即将分析的指标包括 CPU 时间、GPU 时间、JavaScript 堆内存以及应用加载时间。我们的目标是提供一套最全面、免费的分析信息。并且不:多边形计数”不是我们关心的指标

内容 

瓶颈 

如果不找出应用的瓶颈,你的优化努力将不具成效。

示例 

假设你在渲染一个包含许多对象的大型场景。你的应用勉强达到 60 fps。即使你优化了每个对象的顶点数,帧率可能仍然维持在 60 fps。

在这种情况下,CPU 负责将渲染每个对象的命令(“绘制调用”)发送给 GPU。很可能 CPU 的任务过于繁重,导致 GPU 在空闲,等待 CPU 发送更多工作任务。

不过,我们并不知道……直到我们进行测量。这就是分析存在的意义。

瓶颈类型 

应用的任何部分都可能导致瓶颈。以下是一些常见瓶颈类型的例子,按发生频率排序:

CPU 绘制调用:过多的驱动调用导致大量开销。

垃圾:应用正常运行,但产生的垃圾会导致规律或不规律的卡顿。

CPU 逻辑:应用无法快速为 GPU 提供工作。通常由于繁重的物理模拟或光线投射引起。

GPU 片段着色:每个片段的性能成本过高。

GPU 顶点处理:每个顶点的处理需求过大。

GPU 解析:由移动 GPU 上的后期处理导致。

GPU 顶点读取:顶点内存读取速度不够快。

每一种瓶颈可能还有其子瓶颈。

指标 

我们将要分析的指标包括:

CPU 时间 

任何 XR 应用的工作都分为 CPU 和 GPU。CPU 负责为 GPU 准备图形工作并执行应用逻辑。

任何 JavaScript 代码都会在 CPU 上运行,以准备绘制调用、执行资源加载、模拟物理、渲染音频和计算场景图转换。

GPU 时间 

GPU 承担图形处理的重任。虽然 CPU 会发送像“用着色器 Y 和纹理 Z 以及材质参数 W 绘制网格 X”这样的绘制调用,但 GPU 会实际进行光栅化和每个顶点的转换以生成屏幕上的像素。

GPU 还负责将最终图像传输到屏幕,并等待“V-Sync”来同步屏幕的刷新率与应用程序的更新速度。

帧率与 V-Sync 

我们使用帧率(每秒帧数 = fps)来分析我们的应用。

这个指标仅用于解释理解性能与 V-Sync 交互的复杂性。它太粗略无法做出有效判断。

将 V-Sync 想象为_固定的截止时间_:每秒 60、72 或 90 次(帧率)。我们把“达到 V-Sync”称为及时渲染并提交帧以赶上截止时间。

当你错过截止日期时,所有工作都会被丢弃,你需要努力赶上下一个截止日期。 在可变帧率环境中,这可能意味着驱动可能会将帧速率降至一半。

如果应用界面仅比目标速度稍慢,你可能看到 30 fps 而不是 59 fps,从而传达一个完全不同的信息。可能应用正以 3ms 的 CPU 时间和 3ms 的 GPU 时间表现不错,但由于工作开始较晚导致错过 V-Sync,从而帧率减半。 此时,没有顶点计数、绘制调用或其他经典优化能帮助你。

延迟 

延迟,即从输入(如头部运动)到形成最终帧的时间差,对于 VR 来说尤为重要。WebXR 实现通常会帮我们处理这个问题,如果我们没有用完帧预算,可能会稍微推迟一些帧回调,以减少延迟。在 WebXR 中对此的控制有限,因此本文中不作深入探讨。

垃圾回收 

JavaScript 带有内存管理功能,以至于你能够随意进行分配。因此很容易掉以轻心。

由于不需要管理内存,你便失去了在何时管理内存的控制权。这个过程称为“垃圾回收”,会随意地在应用程序生命周期中发生——例如,当你即将达成 V-Sync 并提交帧时。

垃圾回收可能会消耗 0.1 - 10 毫秒。考虑到通常操作 VR 的帧预算是 11 毫秒,你_绝对_不希望这种情况随机发生。

那么我们该如何避免它?唯一的方法就是避免_任何_需要清理的垃圾产生。你生成得越少,垃圾回收间歇就会越小越少。

应用加载时间 

与网站加载类似,用户对使用应用程序的兴趣会随等待时间的增加而减退。由于 WebXR 应用程序相对较大,可能会与网站有所不同,但这并不是必要的。

通过提前加载尚不需要的资源,我们可以减少感知的加载时间。

通过优化资源并确保服务器设置最佳,我们可以减少总加载时间。

通过使用解析耗费较少的格式,我们可以减少 CPU 在下载资源后所需的工作。

工具 

在本文中,我们将介绍以下工具:

Chrome Profiler 

Chrome 自带的分析器可以让你分析 JavaScript 的 CPU 时间、垃圾回收以及粗略的 GPU 帧时间。

你可以通过访问任何网站并按下 Ctrl + Shift + C(MacOS 上为 Command + Shift + C)找到性能标签。找到“Performance”。 要记录分析会话,点击左上角的记录按钮(Ctrl/Command + E)。 通常 3-5 秒就足够了,因为我们关注的通常是个别帧。

Android 设备上的远程调试时同样有效,比如 Meta Quest 或智能手机。

Safari 在 Mac、iOS 设备和 Apple Vision PRO 上具备类似的分析功能(例如,通过 Apple Vision PRO 模拟器运行的 Safari)。

WebXR 分析横幅

Chrome 内存分析器 

垃圾回收部分,我们谈到原本较为流畅的应用程序由于垃圾收集而产生卡顿。

为追踪这个瓶颈,浏览器提供了一种方法来采样 JavaScript 堆。在前面提到的Chrome Profiler中,你可以这样在 Chrome 中启用它:

我们如何分析 WebXR/WebGL 应用

示例 

以下是在 Meta Quest 2 上基于 Three.jsElysian 的分析:

我们如何分析 WebXR/WebGL 应用

你可以看到“JS Heap”在 14.1 MB 到 23.3 MB 之间波动。

每当内存快速下降,就发生了垃圾回收。在这个例子中,GC 所占用的时间很长,以至于推迟了下一帧的开始,导致帧丢失:

我们如何分析 WebXR/WebGL 应用

结果,我们只能希望丢失的帧被前一帧成功预测重建,否则会发生严重的卡顿。 由于动画无法通过预测重建,因此无论如何都会有一些卡顿。

网络选项卡 

任何浏览器的网络选项卡都是分析应用程序加载时间的得力工具。

你可以通过访问任何网站并按下 Ctrl + Shift + C(Mac 上为 Command + Shift + C)找到网络选项卡。 在打开选项卡时重新加载页面可记录网络活动。

下载阻塞 

如果某个资源在应用程序启动时不需要立即使用,应该延迟加载,因为浏览器将在 有限的并行请求内运行(例如,Chrome 是 6 个)。

我们如何分析 WebXR/WebGL 应用

Meta Quest 性能 HUD 

在 Meta Quest 上分析 VR 渲染时,可利用性能 HUD进行操作。

Meta Quest Developer Hub 中可以轻松安装。

这对调试视图相关的性能问题特别有用,因为你能在使用头显时得到持续的性能反馈。

示例 

在以下示例中,Ayushman Johri 分享了他的基于 Wonderland Engine 的“Vintage Study Room”在 Meta Quest 性能 HUD 下的优越性能表现:

OVR GPU Profiler 

如果你遇到顶点或片段着色瓶颈,则需要更清晰地理解你的着色器中哪里耗时。

ovrgpuprofiler 是一个极为犀利的工具。对 GPU 内存和架构有些了解的话,它会给你很大的洞察。

通过 adb 将其安装到你的 Meta Quest 设备上,并通过 adb shell 运行:

 1    支持的 47 个指标:
 2    1       每秒时钟数
 3    2       GPU % 总线繁忙
 4    3       % 顶点获取停滞
 5    4       % 纹理获取停滞
 6    5       每像素 L1 纹理缓存未命中
 7    6       % 纹理 L1 缺失
 8    7       % 纹理 L2 缺失
 9    8       % 系统内存停滞
10    9       每秒预裁剪多边形
11    10      % 初级被拒绝
12    11      % 初级裁剪

(来源:developer.oculus.com

示例输出如下所示:

 1$ adb shell ovrgpuprofiler -r"4,5,6"
 2
 3% 纹理获取停滞                      :           2.449
 4每像素 L1 纹理缓存未命中              :           0.124
 5% 纹理 L1 缺失                         :          20.338
 6
 7% 纹理获取停滞                      :           2.369
 8每像素 L1 纹理缓存未命中              :           0.122
 9% 纹理 L1 缺失                         :          20.130
10
11% 纹理获取停滞                      :           2.580
12每像素 L1 纹理缓存未命中              :           0.127
13% 纹理 L1 缺失
14
15...

(修改自:developer.oculus.com

你可能听说过,在着色器程序中读写内存通常是最昂贵的操作。但其昂贵程度取决于内存操作是否对缓存友好。

L1(“一级”)高速缓存内存速度非常快。要确保利用它,请遵循局部性原则:访问前后彼此接近的内存位置。

Spector.js 

Spector.js 是适用于 Chrome 和 Firefox 的浏览器扩展,可捕获 WebGL 帧跟踪。它能显示完整的命令列表,并总结统计数据,如顶点数和绘制调用。

Chrome 扩展商店Firefox 插件库中安装。你还可以通过 HTML 标签将该工具嵌入不支持插件的浏览器中。

我们如何分析 WebXR/WebGL 应用

首先通过顶部的插件按钮启用工具,然后点击红色的记录按钮录制帧。

我们如何分析 WebXR/WebGL 应用

你可以看到,在这里,Wonderland Engine 绘制了许多对象,总共使用了 11 次绘制调用。对于其他框架,这个数字通常会是它的 10-100 倍。

Disjoint Timer Query 

EXT_disjoint_timer_query 扩展是一个 WebGL 扩展,可用于测量一组 WebGL 命令的 GPU 时间。在 Chrome 中支持较好[截至 2023 年 8 月],并需启用“WebGL Debug Extensions”Chrome 标志。

由于所有命令在 GPU 上异步运行,因此时间测量也需要异步调度。

Wonderland Editor Profiler 

Wonderland Editor 自带分析工具,有助于理解你的 WebXR 应用程序在性能方面可能遭到的挑战。

我们如何分析 WebXR/WebGL 应用

结语 

每一种框架都有其独特的性能特征。大多数会因绘制调用而在其他方面前瓶颈,之后是片段瓶颈——不仅限于90 fps,无需去低多边化!

我们从头规划 Wonderland Engine 避免大多数上述瓶颈——免费高达每年120k 美元的收入。 如需企业许可证和支持,请通过[email protected]联系我们。

立即试用 Wonderland Engine 并开始节省时间优化。

我们如何分析 WebXR/WebGL 应用
Last Update: March 28, 2025

保持更新。