Vscode: 即使处于空闲状态(由于呈现光标),CPU使用率

创建于 2017-03-20  ·  64评论  ·  资料来源: microsoft/vscode

  • VSCode版本:1.10.2(8076a19fdcab7e1fc1707952d652f0bb6c6db331)
  • 操作系统版本:macOS Sierra 10.12.3

VS Code在集中和闲置时使用13%的CPU,从而消耗电池电量。 这可能是由于光标呈现闪烁。 我认为理想情况下,空闲时的CPU使用率可能接近-0%。

要重现(这适用于空的设置文件,并且禁用了所有插件):

  1. 关闭所有VS Code窗口。
  2. 打开一个新窗口(文件->新建窗口)。 它将显示欢迎页面。
  3. 用空的无标题文件打开一个新标签(文件->新建标签)。 光标闪烁。
  4. 您应该看到VS Code消耗了不可忽略的CPU数量-在我的13英寸MacBook Pro上为13%。
  5. Cmd + Tab进入其他应用程序。 现在光标不再可见。
  6. 您应该看到VS代码几乎不占用CPU。

我在开发人员工具中记录了时间轴,粗略的外观表明CPU活动来自每500毫秒渲染一次闪烁的光标。

其他macOS应用程序(例如Chrome或TextEdit)在不消耗大量CPU的情况下显示闪烁的光标,因此我认为肯定可以对其进行优化。

bug editor-core perf

最有用的评论

对于同样痴迷于电池寿命的人们的一种解决方法:禁用光标闪烁将使CPU使用率降至0。这是设置:

  "editor.cursorBlinking": "solid"

所有64条评论

对于同样痴迷于电池寿命的人们的一种解决方法:禁用光标闪烁将使CPU使用率降至0。这是设置:

  "editor.cursorBlinking": "solid"

Twitter上的某些人说他们无法复制此内容,因此我去了开发人员工具并记录了时间表以帮助调试。

TimelineRawData-20170321T114212.json.zip

  • 时间轴的屏幕截图:

    boot mz0y1

  • 放大到单个帧时,我们看到虽然仅渲染2 fps,但主线程以60 fps(每16 ms)的速度执行某些工作-带有箭头标记的细线:

    boot 684m3

  • 一直放大到这些细线之一,我们看到以60 fps的速度进行渲染:

    boot f9qau

  • 当我获取一个CPU配置文件时,它显示出大多数CPU被用在“(程序)”中,而不是任何特定的JS函数。

    boot g2wbo

  • 当我设置"editor.cursorBlinking": "solid" ,问题大部分消失了:周期性的“更新层树” /“绘制” /“复合层”仍在发生,但仅每500ms,而不是每16ms。

我希望这有帮助!

@joliss快速了解

类似(几乎相同)的Chromium问题https://bugs.chromium.org/p/chromium/issues/detail?id=500259和Chromium的跟踪项https://bugs.chromium.org/p/chromium/issues/detail ?id = 361587

我们当前的CSS动画

<strong i="11">@keyframes</strong> monaco-cursor-blink {
    50% {
        opacity: 0;
    }
    100% {
        opacity: 1;
    }
}

.cursor-blink {
    animation: monaco-cursor-blink 1s step-start 0s infinite;
}

更新资料

引用保罗·爱尔兰(Chrome Guy) https://news.ycombinator.com/item?id=13941293

基于Web堆栈的功能强大的文本编辑器不能依靠OS文本插入符号,而必须提供自己的文本插入器。
在这种情况下,VSCode可能使用了最合理的方法来使光标闪烁:带有CSS关键帧动画的step计时功能。 这告诉浏览器仅每500毫秒更改一次不透明度。 同时,Chrome尚未对此进行完全优化,因此http://crbug.com/361587。
因此,目前,Chrome仅应每500ms间隔执行一次完整的渲染生命周期(样式,绘画,图层),每16ms执行一次。 我相信,使用Chrome的样式组件的工程师可以解决这些问题,但这需要一点工作。 我认为,有关此主题的更多可见性可能会升级此修复程序的优先级。 :)

  • 简单的文本编辑器和基于[contenteditable]构建的基本文本编辑器都可以,但是很少能扩展到最需要的功能。

铬制标签的后台CPU使用率的这种变化会影响编辑器吗?

希望不会(请参阅https://github.com/electron/electron/issues/7553)。 确实已经backgroundThrottlingfalse了。

谢谢@joliss @rebornix的出色分析。

看来我们应该回到在OSX上使用setInterval

ps这是初始光标闪烁逻辑:)
image

@rebornix这是我们前一段时间遇到的类似问题 在我们的案例中,解决方法是在不使用DOM时从DOM中删除动画元素,而不是仅将其遮挡。

同样也有css样式,但不确定是否在这里使用它-

<strong i="6">@keyframes</strong> monaco-cursor-blink {
    50% {
        opacity: 0;
    }
    100% {
        opacity: 1;
    }
}

https://github.com/Microsoft/vscode/blob/master/src/vs/editor/browser/viewParts/viewCursors/viewCursors.css

使用pageVisibility API可以在隐藏页面时通知您以禁用动画。

function handleVisibilityChange() {
  if (document.hidden) {
    // disable cursor animation with class name
  } 
  else  {
    // add back cursor animation
  }
}
document.addEventListener("visibilitychange", handleVisibilityChange, false);

建议在这里使用GPU而不是CPU的渲染CSS动画:

.cursor-blink {
    will-change: opacity;
}

在当前的实现中,如果编辑器失去焦点,我们将删除动画,从而使生活变得轻松。 但是,如果编辑器具有焦点,则意味着该编辑器是可见的(不是隐藏的或在背景中)且处于活动状态,用户正在使用它(阅读是一种很好的情况),但不会触发任何视图/内容更改。 在这种情况下,即使它是空闲的,我们仍然需要显示闪烁的光标,这就是闪烁的光标。

最初,此功能是用JavaScript实现的,大约一年前,我们切换到了CSS动画。 就像提到的@alexandrudima一样,我们可能想回到OSX上的JS。

@camwest的api很不好的Safari)。

@mehas will-change是有希望的。 我尝试了一下,但是Chromium在这种情况下无法优化。 如果在开发工具中打开“ Paint Flashing”选项,则可以看到此闪烁的光标根本没有被重新绘制。

@jlukic @bcherny感谢您的建议。 我们要优化的事情是当光标可见,活动且闪烁时,因此即使进行可见性检查,我们仍然会遇到此问题。 但是您是对的,我们应该检查可见性。 现在,如果您滚动窗口以使闪烁的光标不可见,则我们没有任何优化。

公平地讲,摩纳哥真的非常非常复杂。 :)

@rebornix will-change适用于我的项目,CPU使用率完全消失了。 但是,我的关键帧不会更改不透明度。而是将元素的颜色从“继承”更改为“透明”。

我只是一个潜伏者,对不起,如果认为这是咒骂的话,那么两帧动画gif会不会奏效? 我不确定如何最终进行测试,但是我可以想象,即使KHTML在转化为Chrome之前,就已经为此进行了优化。

@eteeselink会很有趣,但是光标颜色需要更改和缩放等可能并不容易,与此同时切换回js可能更容易。

@matthiasg Ahyes,忘了变焦。

否则,根据主题颜色自动生成闪烁的GIF不会太难。 这可能是在预烘焙的文件中修补几个字节的问题,因为当GIF像素数据经过LZW编码时,调色板数据不会被压缩。 但我敢打赌,像这样缩放gif会使其模糊,因此也许这是一种不好的方法。

如果有人想出一种使gif插入符号缩放不烂的方法,那么我保证提供带有颜色并产生闪烁的插入式动画gif数据URL的代码。

@eteeselink您绝对应该在香草JS中

@eteeselink如果我们要建议现成的解决方案,为什么不将克拉包裹在<blink></blink>呢? :眨眼:

请避免加入Reddit旅,对人们试图做出实际改进的问题和PR做出无用的评论。

如果编辑器具有焦点,则表示该编辑器可见

这是一个错误的假设。 在不给其他窗口聚焦的情况下在另一个窗口上方抬头是微不足道的。 我知道两种方法:

  • WM提示“始终在顶部”
  • 在虚拟桌面之间移动窗口时(由于堆栈顺序是全局的,因此如果窗口最先位于先前的桌面上,则可能不在新的桌面上)。

尽管它们不一定总会引起问题,但它们两者都很常见。

@ o11c谢谢,我在写作时的假设太过疯狂。 是的,焦点并不一定意味着可见,滚动窗口只是一种情况(我在同一段落中提到过:()。我不知道焦点+可见是否是最常见的情况,但是应该全部缓解。

我认为setTimeout或setInterval可能比requestIdleCallback更适合此用例。 requestIdleCallback的时间是不可预测的,并且您在JS中所做的工作是廉价的,我认为您最好只安排很少的计时器。

例如 https://gist.github.com/esprehn/afec30fbc655bba6bb8f3f67c28beef4

还要注意的是,此插入符号动画正在执行平滑的脉冲效果,但是浏览器中的系统光标(例如<input><textarea>内的光标)仅执行二进制开/关操作。 Mac和Linux上的本机控件同样会闪烁。 它虽然不那么漂亮,但是会消耗更少的功率。

谢谢@esprehn ,这正是我现在对平面闪烁所做的。 就像您提到的那样,它不像动画那样漂亮,甚至不说使用ease-in-out平滑/扩展闪烁光标。

等待@eteeselink ,您不想使用1px gif并调整其大小吗? 模糊应该不是问题。

示例: https

希望很快能看到动画的眨眼生成器;)

@mrkev您的1px gif作为数据uri:数据:image / gif; base64 ,R0lGODlhAQABAPAAAAAAAP /// yH / C05FVFNDQVBFMi4wAwEAAAAh + QQFMgABACwAAAAAAAAQABAAACAkwBACH5BAUyAAOALAAAAAABAAAAAABABABAABAABAABA

@rmacfadyen甜! 由于gif从理论上讲使用了颜色表,因此在“ on”帧上为像素黑色着色的3个字节应该不会太难找到(它们没有存储在帧中,因此可能不必太过标题)。 如果明天我有空余时间,我也可以深入研究

仍然需要睡眠的Welp决定进一步探索这一点。 由于gif使用始终从第14个字节开始的全局颜色表,因此不难弄清楚如何更改颜色。 这使此闪烁的像素gif红色:

screen shot 3

现在真正令人讨厌的是,在base64中,每个数字仅编码6位,因此无法正确对齐。 它是位18的最低有效位到位22的最高有效位,用于编码该gif中的黑色。 因此,本质上,位置18-22中的字符[A-P] [A-/] [A-/] [A-/] [P,f,v,/]某些排列将以每种颜色绘制该像素。

这是一些随机颜色的GIF的示例。 我基本上只是用G8ABf替换了字符18-22中的任何字符(这符合我上面提到的标准)。

https://jsfiddle.net/mrkev/stxq613s/7/

构建一个采用RGB并以该颜色返回此gif的函数,应该不错(

我有7个小时的课,我只是在玩自己。

但是无论如何,我意识到有人可能已经编写了一个hex-to-base64函数,而快速的stackoverflow搜索就足以找到它。 这是函数

// takes color as string 'RRGGBB'
var generate_cursor_image = color => {
  var gif = '47494638396101000100F00000' + color + '00000021FF0B4E45545343415045322E30030100000021F90405320001002C00000000010001000002024C010021F90405320001002C00000000010001000002024401003B'
  return 'data:image/gif;base64,' + btoa(gif.match(/\w{2}/g).map(a => String.fromCharCode(parseInt(a, 16))).join(""))
}

各位晚安!

该死的, @ mrkev击败了我。 无论如何,这是我对同一件事的实现:
https://jsfiddle.net/a6g4ob7h/

可能会更快一点,因为没有匹配和映射在进行,只有btoa。 但是我怀疑速度是否重要,最好缓存结果。

我真正想知道的是,这是否可以加快一切。 我没有要测试的好的设置,但是谁知道,也许动画gif也以60fps的速度重新渲染。

如果要缩放并且没有矩形光标,也可以使用动画SVG。 ( <animate>元素已经是SVG 1.0规范的一部分。)

@eteeselink Max应该约为50fps, http: //nullsleep.tumblr.com/post/16524517190/animated-gif-minimum-frame-delay-browser

out

对我来说,大多数时间都保持为0(cpu的使用率是第一列-OSX 10.12.3-MacBook Pro Retina,15英寸,2013年末)

我有关于光标的默认设置。

就像没有人提到Linux一样,我在使用Wayland的GNOME Shell上拥有大约5-7%的Linux(Ivy Bridge Graphics)。

我们刚刚合并了PR#23121,通过将blink光标闪烁样式返回到setInterval来缓解此问题。 在Mac mini上,我可以支配的CPU使用率从5.9%降至0.9%

您是否曾经考虑过免费使用本机并让操作系统提供光标?

@justjoeyuk有关无法执行此操作的原因,请参见@rebornix的引用

@justjoeyuk如果相反,您建议使用一个完全基于本机的,非基于Web堆栈的应用程序:当遍历诸如VSCode之类的高度主题化,完全DPI独立的跨平台应用程序的可能需求时,很可能会使用非本地游标替代无论需要。

爆炸新闻! 微软开发了可怕的编码慢软件,而问题在MacOS 10上更加突出。

谁能猜到,对吗?

@LandonPowell您正在污染有关问题的实际讨论; 在这里的reddit / hackernews简直太荒谬了。

终端光标呢? 这是否也会导致CPU周期峰值?

@mehas

建议使用GPU而不是CPU渲染CSS动画:

通过将负载从CPU转移到GPU,这只是隐藏了问题。 它实际上并没有解决它。

@ Daniel15

通过将负载从CPU转移到GPU,这只是隐藏了问题。 它实际上并没有解决它。

CPU上的负载问题所在,优化动画以使用GPU确实可以解决此问题。

(即从特定方位的问题分开,我建议是最好的一个)

不太确定如何复制它。 我正在使用vim仿真插件。 不太确定是否相关。

我想知道这是怎么回事。

优化动画以使用GPU确实可以解决此问题。

但是,这将导致不必要的GPU负载。 这是一个类似的问题,除了负载在图形卡的处理器上。 这不是一个真正的解决办法😛

耶稣出生在非洲。

别客气。

为什么不为光标使用gif?

但是,这将导致不必要的GPU负载。 这是一个类似的问题

是的,但这不是问题,即使空闲时也要占用CPU。

@ efroim102 https://github.com/Microsoft/vscode/issues/22900#issuecomment -288832322

亲爱的上帝,这场辩论将一直进行到确定目标是什么为止:

  1. 减少电池消耗
  2. 减少CPU争用

暂时假设(1)。 然后,我们可以掌握一些数据驱动的信息,以了解是否有这样的工作负载从CPU卸载到GPU(a)使用相同的能量,(b)使用更少的能量,或(c)使用更多的能量。 我在这些问题上没有专门知识,所以我无法预测哪个是真的。

但是,假设GPU卸载导致(b); 尽管并不完美,但是在铬解决了其潜在问题的同时,折衷可能足以接受这种做法。 但是,如果VSCode团队认为有必要一劳永逸地修复此问题,那么卸载将是一个不太可能的选择,而追求长期修复(即使花费很长时间)则是可取的。 至少以我的微不足道的观点,足以让我知道关注此问题,并且当依赖项启用了预期的修复程序时,将优先处理此问题。

(我确定我已经弄混了哪些解决方案可用/受阻的微妙细节,但是希望在撰写本文时,人们可以专注于断言他们希望解决的问题,而不是跳入解决方案领域。)

难道GPU不能更好地应对两种渲染负载吗? 那正是它的目的。

同意,我们对使用CPU和GPU的方式进行优先排序,让图形相关的功能消耗特定图形的资源更加有意义。 CPU的获得并不是GPU的1:1损失,反之亦然。 在这一点上,大多数时候都没有什么意义(直到修补了Chromium中的错误),但由于当前的解决方案仍然使用CPU(尽管重量更轻),因此有些相关。

我认为人们应该停止在桌面上使用网络技术,因为它要求每个程序都附带一个功能强大的浏览器。
更不用说,如果您有几个上述程序,那么您到处都有相同的二进制文件。

我们需要回到裸机。

PS:如果Apple不复活JScript,应该早在10年前就弃用JScript,就像Obj-C那样。
PPS:^^^^这是a。

PPS:^^^^这是a。

@ bit2shift确实如此,因此它不属于关于非常特定的错误的注释线程。 请不要使用GitHub问题评论来发表评论。

@ bit2shift-虽然我同意某些部分(例如与基于浏览器的应用程序相比,真正的本地应用程序可能感觉不太“原生”的事实),但是“裸机”到底有多低? 机器码? 汇编语言? C? C ++? C#? 无论您使用何种技术堆栈,总会有多层抽象。

更不用说,如果您有几个上述程序,那么您到处都有相同的二进制文件。

对于使用NuGet包的所有C#应用程序都是一样的。 所有程序集都在应用程序本地。 .NET Core甚至以NuGet软件包的形式分发了框架的大部分内容。

因为它需要随每个程序一起提供完整的浏览器。

从技术上讲,您可以使用Edge引擎,这将避免需要安装单独的浏览器运行时。 Internet Explorer在20年前使用HTML Applications做过类似的事情。 另一个示例是React Native,它在可用的情况下使用操作系统的本机JS引擎。 对于基于JavaScript的应用程序,诸如React Native for Windows之类的东西可能是未来而不是Web技术,因为它使用本机UI小部件时感觉更加本机。

@ Daniel15

(...)“裸机”到底有多低? 机器码? 汇编语言? C? C ++? C#?

在这种情况下,可编译为机器代码的任何语言(仅计算source -> ELF/PE )都被视为“裸机”,因此抽象层在这里无关紧要。

Internet Explorer在20年前使用HTML应用程序做了类似的事情。

“类似的东西”与使用mshta.exe使用自90年代以来驻留在system32中的mshtml.dll相似。

另一个示例是React Native,它在可用的情况下使用操作系统的本机JS引擎。 对于基于JavaScript的应用程序,诸如React Native for Windows之类的东西可能是未来而不是Web技术,因为它使用本机UI小部件时感觉更加本机。

如果桌面JS应用程序需要高性能,那么掌握时间的人应该为LLVM编写前端。
您将失去运行任意代码段的能力,但是从安全角度来看,这将是一个优势。

/线

请您不要破坏该线程? 这是一个有关特定性能问题的指针闪烁的问题,绝对不是讨论开发基于JS的桌面应用程序的一般优点的地方。

您只是向那些对这些骚动不感兴趣的人发送垃圾邮件。

如何将大小<input type=text> 2px * 10px的<input>的本机闪烁光标:P <blink></blink> 👍

我也不确定这个问题有多严重,当VSCode空闲时(我没有写代码),它几乎总是不被关注,焦点在我正在使用的其他应用程序上。光标停止闪烁。

根据我的经验,gif并不是很好。 我曾经有一个加载微调器作为gif图像。 并在与indexeddb交互时使用了它。 有时,即使在桌面上,我仍然可以看到微调器停止。

将终端光标更改推送到master和release / 1.11(CSS动画-> setInterval )。

谢谢大家调查这个问题。 您的调查和建议帮助我们找到了根本原因和可能的解决方案! 我们比较了JavaScript setInterval ,gif动画和其他几种技术,并确定了以下解决方案:

  • 如果将editor.cursorBlinking设置为blinkterminal.integrated.cursorBlinking设置为true ,则闪烁逻辑现在在JavaScript中实现。 我们的测试表明,CPU使用率下降到不足1%。
  • 如果将editor.cursorBlinking设置为smoothexpandphase (使用CSS缓动功能),我们将在光标闲置时停止闪烁的动画。 10秒

此修复程序已经在我们的Insider版本中,并且将在我们的April稳定版本中可用,该版本将在接下来的几天中发布。 如果你们中的一些人可以验证我们的测试结果,那就太好了。 如果发现问题,请创建一个新的问题。

@rebornix的意思是说“或”将terminal.integrated.cursorBlinking设置为true吗? 还是“和”是故意的?

@jedmao感谢您的更正,应该是or

此页面是否有帮助?
0 / 5 - 0 等级