VS Code在集中和闲置时使用13%的CPU,从而消耗电池电量。 这可能是由于光标呈现闪烁。 我认为理想情况下,空闲时的CPU使用率可能接近-0%。
要重现(这适用于空的设置文件,并且禁用了所有插件):
我在开发人员工具中记录了时间轴,粗略的外观表明CPU活动来自每500毫秒渲染一次闪烁的光标。
其他macOS应用程序(例如Chrome或TextEdit)在不消耗大量CPU的情况下显示闪烁的光标,因此我认为肯定可以对其进行优化。
对于同样痴迷于电池寿命的人们的一种解决方法:禁用光标闪烁将使CPU使用率降至0。这是设置:
"editor.cursorBlinking": "solid"
Twitter上的某些人说他们无法复制此内容,因此我去了开发人员工具并记录了时间表以帮助调试。
TimelineRawData-20170321T114212.json.zip
时间轴的屏幕截图:
放大到单个帧时,我们看到虽然仅渲染2 fps,但主线程以60 fps(每16 ms)的速度执行某些工作-带有箭头标记的细线:
一直放大到这些细线之一,我们看到以60 fps的速度进行渲染:
当我获取一个CPU配置文件时,它显示出大多数CPU被用在“(程序)”中,而不是任何特定的JS函数。
当我设置"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)。 确实已经将backgroundThrottling
为false
了。
谢谢@joliss @rebornix的出色分析。
看来我们应该回到在OSX上使用setInterval
。
ps这是初始光标闪烁逻辑:)
@rebornix这是我们前一段时间遇到的类似问题。 在我们的案例中,解决方法是在不使用DOM时从DOM中删除动画元素,而不是仅将其遮挡。
同样也有css样式,但不确定是否在这里使用它-
<strong i="6">@keyframes</strong> monaco-cursor-blink {
50% {
opacity: 0;
}
100% {
opacity: 1;
}
}
使用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做出无用的评论。
如果编辑器具有焦点,则表示该编辑器可见
这是一个错误的假设。 在不给其他窗口聚焦的情况下在另一个窗口上方抬头是微不足道的。 我知道两种方法:
尽管它们不一定总会引起问题,但它们两者都很常见。
@ o11c谢谢,我在写作时的假设太过疯狂。 是的,焦点并不一定意味着可见,滚动窗口只是一种情况(我在同一段落中提到过:()。我不知道焦点+可见是否是最常见的情况,但是应该全部缓解。
我认为setTimeout或setInterval可能比requestIdleCallback更适合此用例。 requestIdleCallback的时间是不可预测的,并且您在JS中所做的工作是廉价的,我认为您最好只安排很少的计时器。
例如 https://gist.github.com/esprehn/afec30fbc655bba6bb8f3f67c28beef4
还要注意的是,此插入符号动画正在执行平滑的脉冲效果,但是浏览器中的系统光标(例如<input>
或<textarea>
内的光标)仅执行二进制开/关操作。 Mac和Linux上的本机控件同样会闪烁。 它虽然不那么漂亮,但是会消耗更少的功率。
谢谢@esprehn ,这正是我现在对平面闪烁所做的。 就像您提到的那样,它不像动画那样漂亮,甚至不说使用ease-in-out
平滑/扩展闪烁光标。
@mrkev您的1px gif作为数据uri:数据:image / gif; base64 ,R0lGODlhAQABAPAAAAAAAP /// yH / C05FVFNDQVBFMi4wAwEAAAAh + QQFMgABACwAAAAAAAAQABAAACAkwBACH5BAUyAAOALAAAAAABAAAAAABABABAABAABAABA
@rmacfadyen甜! 由于gif从理论上讲使用了颜色表,因此在“ on”帧上为像素黑色着色的3个字节应该不会太难找到(它们没有存储在帧中,因此可能不必太过标题)。 如果明天我有空余时间,我也可以深入研究
仍然需要睡眠的Welp决定进一步探索这一点。 由于gif使用始终从第14个字节开始的全局颜色表,因此不难弄清楚如何更改颜色。 这使此闪烁的像素gif红色:
现在真正令人讨厌的是,在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
对我来说,大多数时间都保持为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独立的跨平台应用程序的可能需求时,很可能会使用非本地游标替代无论需要。
谁能猜到,对吗?
@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)。 然后,我们可以掌握一些数据驱动的信息,以了解是否有这样的工作负载从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
设置为blink
或terminal.integrated.cursorBlinking
设置为true
,则闪烁逻辑现在在JavaScript中实现。 我们的测试表明,CPU使用率下降到不足1%。editor.cursorBlinking
设置为smooth
, expand
或phase
(使用CSS缓动功能),我们将在光标闲置时停止闪烁的动画。 10秒此修复程序已经在我们的Insider版本中,并且将在我们的April稳定版本中可用,该版本将在接下来的几天中发布。 如果你们中的一些人可以验证我们的测试结果,那就太好了。 如果发现问题,请创建一个新的问题。
@rebornix的意思是说“或”将terminal.integrated.cursorBlinking
设置为true
吗? 还是“和”是故意的?
@jedmao感谢您的更正,应该是or
。
最有用的评论
对于同样痴迷于电池寿命的人们的一种解决方法:禁用光标闪烁将使CPU使用率降至0。这是设置: