由于游标闪烁,Visual Studio代码消耗了13%的CPU资源



本周有趣的问题编号22900受到了Github用户的特别关注。

该问题的详细描述在Visual Studio代码( vscode )代码编辑器的存储库中。 开源开发人员Jo Liss被称为Broccoli和其他免费库的创建者。 在项目页面上,她注意到,如果窗口处于焦点位置,Visual Studio Code将使用处理器的13%的计算资源。 因此,笔记本电脑上的电池电量被浪费了。 程序如此奇怪的行为可能是什么原因?

Joe Liss建议将CPU的活动与呈现光标闪烁相关联-光标状态每秒更改两次,即每500 ms(2 fps)更改一次。

要重现该问题,请执行以下步骤:

  1. 关闭Visual Studio Code中的所有窗口。
  2. 打开一个新窗口(文件→新建窗口)。
  3. 用空文件打开一个新选项卡(文件→新建选项卡)。 光标闪烁。
  4. 在资源监视器中,您将看到计算资源的非零消耗(在装有OS X的薄型笔记本电脑上为13%,在具有Wayland的强大GNOME Shell(Ivy Bridge Graphics)上约为5-7% )。
  5. 切换到另一个应用程序窗口(Cmd + Tab)。 光标不再可见。
  6. Visual Studio Code的CPU消耗减少到几乎为零。

有人需要它,这是在开发人员工具中编写的时间轴: TimelineRawData-20170321T114212.json.zip (请参见上面的屏幕截图)。

如果放大一帧,则可以看到尽管闪烁频率为2 fps,但主线程还是以60 fps的速度工作,也就是说,每16 ms渲染一次。



如果将其拉近一点,可以看到光标以60帧/秒的速度渲染的具体工作。 这些是周期性的“更新层树” /“绘制” /“复合层”,即更新层树



开发人员注意到,在其他macOS Sierra 10.12.3应用程序(包括Chrome和TextEdit)中,光标闪烁而没有明显的CPU消耗。

Visual Studio代码编辑器的用户可以关闭程序中的光标闪烁。 在这种情况下,CPU消耗将减少到0%。 “ Update Layer Tree” /“ Paint” /“ Composite Layers”循环仍然有效,但仅每500毫秒一次,而不是每16毫秒一次。

"editor.cursorBlinking": "solid"

Visual Studio Code中的这种有趣的故障类似于经典的npm 制动指示器问题 。 在npm 3.5.2中,当进度指示器亮起时,该操作的执行速度比不使用该指示器时慢了约50%。

 $ rm -r node_modules $ npm set progress=false $ time npm install npm install 19.91s user 2.66s system 71% cpu 31.667 total $ rm -r node_modules $ npm set progress=true $ time npm install npm install 33.26s user 3.19s system 74% cpu 48.733 total 

是什么原因


当然,当光标闪烁时,CPU消耗的原因与使用活动进度指示器降低npm速度的原因完全不同。 如果您在Chrome浏览器中使用CSS关键帧动画查看几乎相同的错误 ,则可以猜测光标问题的原因。 在那里,开发人员写道,在JavaScript中,闪烁的游标通常消耗1.2%的CPU资源,而在CSS中,由于某种原因,它要多6倍,即7-8%。

该代码似乎是正确的:

 @keyframes monaco-cursor-blink { 50% { opacity: 0; } 100% { opacity: 1; } } .cursor-blink { animation: monaco-cursor-blink 1s step-start 0s infinite; } 

但是问题是Chromium引擎将动画动画强制为60 fps,迫使动画每16毫秒执行一次。

因此,Visual Studio代码编辑器显然使用最合逻辑的方法来实现闪烁的光标功能:这是CSS关键帧动画的step功能。 尽管已经持续了两年多,但Chromium中的此错误尚未完全修复 。 因此,Chrome每16毫秒执行一次完整的渲染周期,因为它应该每秒60帧。 也许当前的讨论将引起对旧bug的关注-开发人员将最终开始实践它。

Visual Studio Code开发人员承认此功能最初是用JavaScript实现的,但是大约一年前,他们改用了CSS。 在当前的实现中,如果窗口未聚焦,则将禁用动画,并且不会过多消耗处理器资源,但是活动窗口确实存在问题。 开发人员认为,在这种情况下,从CSS返回JS是有意义的。

建议同事也考虑将光标实现为动画gif。 您可以根据编辑器的配色方案自动生成此类文件。 的确,缩放可能会有困难:毕竟,缩放时光栅图形将变得模糊。

但是最后,Microsoft的开发人员仍然决定返回旧的JS方法setInterval来使光标闪烁-并且CPU消耗立即减少了好几倍

Source: https://habr.com/ru/post/zh-CN402601/


All Articles