参加你附近的 ,了解 VS Code 中的 AI 辅助开发。

集成终端性能改进

2017年10月3日 Daniel Imms, @Tyriar

为了即将发布的Visual Studio Code 1.17版本,集成终端的渲染引擎已被完全重写,旨在提升性能。在此版本中,我们摒弃了基于DOM的渲染系统,转而使用HTML canvas元素。

DOM渲染

这有些令人惊讶,但在一个旨在显示静态文档的系统中渲染一个交互式终端是可行的。然而,随着时间的推移,我们发现DOM提供的某些功能需要被覆盖才能解决一些问题。

选择:为了满足终端的使用场景,我们做了大量工作来对抗DOM的选择系统。由于我们总是只渲染DOM中可见的内容,因此在不重新实现选择的情况下,您无法选择多页内容。滚动也会导致选择被丢弃。为了解决这些问题,我们添加了自定义选择逻辑。

字符错位:由于许多等宽字体对某些Unicode字符并非严格等宽,这可能导致如下图右侧所示的情况。

Characters to the right of the terminal could become misaligned when Unicode was used

一个解决方法是将所有Unicode字符包裹在固定宽度的span中,但这会增加渲染一帧所需的时间。

过多的垃圾回收:由于渲染终端所需的元素数量,垃圾回收器需要频繁清理内存,这通常会使渲染时间明显延长。我们设置了一个对象池来尝试解决这个问题,允许DOM元素被回收。

性能:无论我们多么努力地解决这些问题,性能始终会受到布局引擎的硬性限制。

绕过布局引擎

在某些情况下,组合元素和执行布局本身可能比一帧(16.6毫秒)花费的时间更长,如果我们想在终端中保持每秒60帧(FPS)的流畅度,这是不可接受的。解决方案是采用新的基于canvas的渲染引擎。

<canvas> HTML元素允许使用JavaScript API绘制图形和文本。

渲染层

通过使用一些被称为“渲染层”的canvas元素来简化终端不同部分的渲染。

当前图层按顺序排列如下:

  1. 文本:背景颜色和前景文本,此层不透明。
  2. 选择:使用鼠标进行选择。
  3. 链接:悬停在链接上时的下划线。
  4. 光标:终端的光标。

将这些部分分离成各自的小组件极大地简化了绘图方式。

只绘制更改的部分

新渲染器的重要一部分是它只绘制发生变化的部分。为此,它维护了一个精简的内部模型,其中包含关于单元格绘制状态的最小信息量。然后,该状态用于在执行更昂贵的绘制操作之前快速检查单元格是否需要更改。对于文本层,此模型包括对字符、文本样式、前景色和背景色的引用。

这与之前的渲染引擎形成了对比,在之前的引擎中,即使没有发生任何变化,整行也会从DOM中移除,然后重建并重新添加。

Only individual character changes are now drawn to the screen

上图中的绿色矩形表示重绘区域。

纹理图集

纹理图集用于进一步提升渲染时间。后台有一个 ImageBitmap,其中包含在默认背景色上以最常见样式显示的所有ASCII字符。

绘制这些样式的文本时,使用的是纹理图集,而不是常规调用 CanvasRenderingContext2D.fillText。由于ImageBitmap位于GPU上,绘图速度得到了显著提高。

Behind the scenes an image is maintained containing the most common characters

强制跳帧

由于DOM中的渲染速度,有必要跳过额外的帧以确保解析器有足够的CPU时间。虽然这使得命令运行速度比以前更快,但大量数据流经终端会导致帧率降至10 FPS以下。

有了新的渲染器,这个限制已被移除,您现在可以在终端中享受高达60 FPS的速度。

60 frames per second is now possible in the terminal

结果

我们的基准测试显示,集成终端的渲染速度现在比以前快了大约 5到45倍,具体取决于情况。即使您没有注意到响应速度和帧率的提高,更快的渲染也意味着更少的电池使用!我们希望您喜欢这些性能改进,它们将在几天后随VS Code 1.17版本发布,并且现在可以在Insiders 版本中进行测试。

您还可以查看原始的 xterm.js 拉取请求,其中添加了该功能,以了解更详细的信息。

编码愉快!

Daniel Imms,VS Code 团队成员 @Tyriar

© . This site is unofficial and not affiliated with Microsoft.