Vscode: アイドル時でもCPU使用率(カーソルレンダリングによる)

作成日 2017å¹´03月20日  Â·  64コメント  Â·  ソース: microsoft/vscode

  • VSCodeバージョン:1.10.2(8076a19fdcab7e1fc1707952d652f0bb6c6db331)
  • OSバージョン:macOS Sierra 10.12.3

VS Codeは、フォーカスされてアイドル状態のときに13%のCPUを使用し、バッテリーを消耗します。 これは、カーソルのレンダリングが点滅していることが原因である可能性があります。 フォーカスアンドアイドル時のCPU使用率は、理想的には0%近くになると思います。

再現するには(これは空の設定ファイルで機能し、すべてのプラグインが無効になっています):

  1. すべてのVSCodeウィンドウを閉じます。
  2. 新しいウィンドウを開きます([ファイル]-> [新しいウィンドウ])。 ウェルカムページが表示されます。
  3. 無題のファイルが空の状態で新しいタブを開きます([ファイル]-> [新しいタブ])。 カーソルが点滅しています。
  4. VSCodeが無視できない量のCPUを消費しているのがわかるはずです。私の13インチMacBookProでは13%です。
  5. 他のアプリケーションへのCmd + Tab。 これで、カーソルは表示されなくなります。
  6. VSCodeが実質的にCPUを消費していないことがわかります。

開発ツールでタイムラインを記録しましたが、ざっと見たところ、CPUアクティビティは500ミリ秒ごとに点滅するカーソルのレンダリングによるものであることがわかりました。

ChromeやTextEditのような他のmacOSアプリケーションは、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ミリ秒ごと)でいくつかの作業を実行していることがわかります。矢印でマークされた細い線です。

    boot 684m3

  • これらの細い線の1つにズームインすると、60fpsでレンダリングが行われていることがわかります。

    boot f9qau

  • CPUプロファイルを取得すると、特定のJS関数ではなく、「(プログラム)」で使用されているCPUのほとんどが表示されます。

    boot g2wbo

  • "editor.cursorBlinking": "solid"を設定すると、問題はほとんどなくなります。定期的な「レイヤーツリーの更新」/「ペイント」/「複合レイヤー」が引き続き発生しますが、16ミリ秒ごとではなく、500ミリ秒ごとにのみ発生します。

これがお役に立てば幸いです。

@joliss内部で起こっていることへのクイックアンサー:ネイティブアニメーションはChromiumの60hzで更新されます。

同様の(ほぼ同じ)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;
}

更新

Paul Irish(Chrome guy)の引用https://news.ycombinator.com/item?id=13941293

Webスタック上に構築された強力な*テキストエディタは、OSテキストカレットに依存できず、独自に提供する必要があります。
この場合、VSCodeはおそらくカーソルを点滅させるための最も合理的なアプローチを使用しています:CSSキーフレームアニメーションを備えたstepタイミング関数。 これにより、ブラウザは500ミリ秒ごとにのみ不透明度を変更するようになります。 一方、Chromeはまだこれを完全に最適化していないため、 http://crbug.com/361587です。
そのため、現在、Chromeは16ミリ秒ごとに完全なレンダリングライフサイクル(スタイル、ペイント、レイヤー)を実行していますが、500ミリ秒間隔でのみその作業を実行する必要があります。 Chromeのスタイルコンポーネントに取り組んでいるエンジニアはこれを解決できると確信していますが、少し手間がかかります。 このトピックに関する可視性の追加により、修正の優先順位が上がる可能性が高いと思います。 :)

  • 単純なテキストエディタ、および[contenteditable]に基づいて構築された基本的なエディタは可能ですが、それらが最も必要な機能セットに拡張されることはめったにありません。

クロムタブのバックグラウンドCPU使用率に関するこの変更は、エディターに影響しますか?

うまくいけない(https://github.com/electron/electron/issues/7553を参照)。 当社はない設定backgroundThrottlingにfalseしばらくすでに以来。

素晴らしい分析をしてくれた@ joliss @ rebornixに感謝します。

OSXでsetInterval使用に戻る必要があるようです。

psこれが最初のカーソル点滅ロジックです:)
image

@rebornixこれは私たちがしばらく前に遭遇した同様の問題。 この場合の回避策は、アニメーション要素を単に閉塞するのではなく、使用されていないときに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

カーソルアニメーションにhttps://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallbackを使用してみませんか?

ページが非表示になったことを通知する

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

CPUの代わりにGPUを使用してCSSアニメーションをレンダリングするためのここでの提案:

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

現在の実装では、エディターがフォーカスを失った場合、アニメーションを削除して作業を楽にします。 ただし、エディターにフォーカスがある場合は、エディターが表示され(非表示またはバックグラウンドではない)アクティブであり、ユーザーはエディターで作業していますが(読み取りは良いケースです)、ビュー/コンテンツの変更はトリガーされません。 この場合、アイドル状態であっても点滅カーソルを表示する必要があります。これが点滅カーソルです。

当初、この機能はJavaScriptで実装されていましたが、約1年前にCSSアニメーションに切り替えました。 @alexandrudimaが述べたように、OSXのJSに戻りたいと思うかもしれません。

@camwestは、APIが魅力的であり、唯一の

@mehas will-changeは有望です。 試してみましたが、この場合、Chromiumは最適化されません。 開発ツールで[点滅のペイント]オプションをオンにすると、この点滅しているカーソルがまったく再ペイントされていないことがわかります。

@ jlukic @ bchernyご提案ありがとうございます。 最適化したいのは、カーソルが表示され、アクティブで点滅しているときです。そのため、可視性チェックを行っても、この問題は引き続き発生します。 しかし、あなたは正しいです、私たちは可視性をチェックする必要があります。 現在、ウィンドウをスクロールして点滅しているカーソルを非表示にした場合、最適化は行われません。

公平を期すために、モナコは本当に、本当に、本当に複雑です。 :)

@rebornix will-変更は私のプロジェクトで機能し、CPU使用率は完全になくなりました。 ただし、私のキーフレームは不透明度を変更しません。代わりに、要素の色を「継承」から「透明」に変更します。

私はただの潜伏者であり、これが罵倒と見なされた場合は申し訳ありませんが、2フレームのアニメーションGIFでうまくいきませんか? これを最終的にテストする方法は完全にはわかりませんが、Chromeに変換されるずっと前に、KHTMLでさえすでにそのための最適化されたパスを持っていたと想像できました。

@eteeselinkは興味深いものですが、カーソルの色を変更したりズームしたりする必要があるなど、簡単ではないかもしれません。それまでの間、jsに戻す方が簡単かもしれません。

@matthiasg Ahyes、ズームを忘れました。

それ以外の場合は、テーマの色に基づいて点滅するGIFを自動生成するのはそれほど難しくありません。 GIFピクセルデータはLZWでエンコードされていますが、パレットデータは圧縮されていないため、プリベイクされたファイルの数バイトにパッチを適用する必要があります。 しかし、そのようなgifをズームするとぼやけてしまうので、それでもこれは悪いアプローチかもしれません。

誰かがgifキャレットのズームを邪魔しないようにする方法を思い付くことができれば、色を取り、点滅するキャレットのアニメーションgifデータURLを生成するコードを提供することを約束します。

@eteeselinkとにかく、バニラJSでは、おそらくPHPと他のいくつかのフレーバーも絶対に要点を

@eteeselinkオフザウォールのソリューションを提案する場合は、代わりにカラットを<blink></blink>でラップしてみませんか? :ウィンク:

人々が真の改善を試みている問題やPRについて、無駄なコメントをすることでReddit旅団に参加することは控えてください。

エディターにフォーカスがある場合は、エディターが表示されていることを意味します

これは誤った仮定です。 フォーカスを与えずにウィンドウを別のウィンドウの上に上げるのは簡単です。 私が知っている2つの方法:

  • 「常に上に描く」WMヒント
  • ウィンドウが仮想デスクトップ間で移動されたとき(スタックの順序はグローバルであるため、ウィンドウが前のデスクトップに最優先されていた場合、新しいデスクトップにはない可能性があります)。

どちらもそれ自体で非常に一般的ですが、必ずしも問題を引き起こすとは限りません。

@ o11cありがとう、書くときの私の仮定はあまりにもワイルドでした。 はい、フォーカスは必ずしも表示される必要はありません。ウィンドウのスクロールは1つのケースです(同じ段落でこれについて説明しました:()。フォーカス+表示が最も一般的なケースかどうかはわかりませんが、すべて軽減する必要があります。

setTimeoutまたはsetIntervalは、requestIdleCallbackよりもこのユースケースにおそらく適していると思います。 requestIdleCallbackのタイミングは予測できず、JSで行っている作業は安価です。頻度の低いタイマーをスケジュールするだけでよいと思います。

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

また、このキャレットアニメーションはスムーズなパルス効果を実行していますが、ブラウザのシステムカーソル(例: <input>または<textarea>内のカーソル)はバイナリのオン/オフのみを実行していることにも注意してください。 。 MacとLinuxのネイティブコントロールも同様に、代わりに点滅します。 あまりきれいではありませんが、使用する電力はかなり少なくなります。

@esprehnに感謝しease-in-outを使用する滑らかな/拡大する点滅カーソルを言うことさえありません。

@eteeselinkを待って

例: https :

そのアニメーションのまばたきキャレットジェネレータをすぐに見たいと思っています;)

@mrkev your 1px gif as data uri: data:image / gif; base64 、R0lGODlhAQABAPAAAAAAAP /// yH / C05FVFNDQVBFMi4wAwEAAAAh + QQFMgABACwAAAAAAAAQABAAACAkwBACH5BAUyAAOALAAAAABABAC

@rmacfadyen甘い! gifは理論的にはカラーテーブルを使用するため、「オン」フレームのそのピクセルを黒に着色する3バイトは、見つけるのが難しくないはずです(フレームに格納されていないため、ヘッダーを深く通過する必要はありません。 )。 明日暇があれば、もっと深く掘り下げることができます

とにかく睡眠が必要なウェルプは、これをもう少し詳しく調べることにしました。 gifは常に14バイト目から始まるグローバルカラーテーブルを使用するため、色を変更する方法を理解するのは難しくありませんでした。 これにより、この点滅するピクセルgifが赤になりました。

screen shot 3

さて、本当に厄介なのは、base64では各桁が6ビットしかエンコードしないため、物事が適切に整列しないことです。 これは、桁18の最下位ビットから桁22の最上位ビットまで、そのgifの黒色をエンコードします。 したがって、基本的に、位置18〜22の文字[A-P] [A-/] [A-/] [A-/] [P,f,v,/]いくつかの順列は、すべての色でそのピクセルを描画します。

これは、ランダムな色のGIFの例です。 私は基本的に、18〜22文字の文字をG8ABf置き換えました(これは上記の基準に適合します)。

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

RGBを受け取り、このgifをその色で返す関数を作成するのはそれほど悪くないはずです(:

私は7時間で授業を受け、文字通り自分で遊んでいます。

しかし、いずれにせよ、誰かがすでにhex-to-base64関数を作成していて、スタックオーバーフローをすばやく検索するだけでそれを見つけることができることに気づきました。 これが関数です。

// 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最大値は約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(Ivy Bridge Graphics)を使用したGNOME Shellでは約5〜7%です。

blinkカーソル点滅スタイルのsetIntervalに戻ることで、これを軽減するPR#23121をマージしました。 Mac miniでは、CPU使用率が5.9%から0.9%に低下します。

ネイティブになり、OSにカーソルを無料で提供させることを検討したことがありますか?

@justjoeyukこれができない理由については、上記の@rebornixからの引用を参照してください

@justjoeyuk代わりに、完全にネイティブで非Webスタックベースのアプリケーションを提案している場合:VSCodeのような、テーマが大きく、完全にDPIに依存しない、クロスプラットフォームアプリケーションの可能性のあるニーズを横断する場合、非ネイティブのカーソル代替が関係なく必要です。

速報! Microsoftは、ひどくコーディングされた遅いソフトウェアを作成しており、MacOS10では問題がさらに顕著になっています。

誰が推測したでしょうか?

@LandonPowellあなたは問題についての実際の議論を汚染しています。 ここでのreddit / hackernewsのブリゲードはばかげています。

ターミナルカーソルはどうですか? それはCPUサイクルにもスパイクを引き起こしていますか?

@mehas

CPUの代わりにGPUを使用して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)につながると仮定しましょう。 完全ではありませんが、Chromiumが根本的な問題に対処している間、またはその場合、トレードオフはこのパスを追求するのに十分許容できる可能性があります。 ただし、VSCodeチームがこれを完全に修正する必要があると判断した場合、オフロードを選択することはほとんどありません。長期的な修正を追求することをお勧めします(かなり時間がかかる場合でも)。 少なくとも私の取るに足らない意見では、この問題に注意が向けられており、依存関係によって意図した修正が有効になったときに優先されることを知っていれば十分です。

(どのソリューションが利用可能/ブロックされているかについての微妙な詳細のいくつかを混乱させたと確信していますが、これを書くことで、人々がソリューション空間に飛び込むのではなく、解決したい問題を主張することに集中できることを望んでいます。)

どちらの方法でも、GPUはレンダリングの負荷に対処するための設備が整っていませんか? それはまさにそれが作られたものです。

同意しました。CPUとGPUの使用方法を優先し、グラフィックス関連の機能でグラフィックス固有のリソースを使い果たす方が理にかなっています。 CPUの増加はGPUの1:1の損失ではなく、その逆も同様です。 この時点では(Chromiumのバグにパッチが適用されるまで)ほとんど意味がありませんが、現在のソリューションではCPUを使用しているため(重量ははるかに少ないですが)、ある程度関連性があります。

プログラムごとに本格的なブラウザを出荷する必要があるため、デスクトップでのWebテクノロジの使用をやめるべきだと思います。
言うまでもなく、上記のプログラムがいくつかある場合は、同じバイナリがいたるところに複製されています。

ベアメタルに戻る必要があります。

PS:Appleが復活していなければ、JScriptはObj-Cと同じように、10年前に廃止されるべきでした。
PPS:^^^^これは暴言です。

PPS:^^^^これは暴言です。

@ bit2shift確かにそうです、そしてそれ

@ bit2shift-私はいくつかの部分に同意しますが(ブラウザベースのアプリはおそらく真のネイティブアプリと比較してかなり「ネイティブ」に感じられないという事実など)、「ベアメタル」はどのくらい低レベルですか? マシンコード? アセンブリ言語? C? C ++? C#? テクノロジースタックに関係なく、常にいくつかの抽象化レイヤーがあります。

言うまでもなく、上記のプログラムがいくつかある場合は、同じバイナリがいたるところに複製されています。

ただし、NuGetパッケージを使用するC#アプリでも同じです。 すべてのアセンブルはアプリに対してローカルです。 .NET Coreは、フレームワークの大部分をNuGetパッケージとして配布します。

各プログラムに本格的なブラウザを同梱する必要があるためです。

技術的には、Edgeエンジンを使用できます。これにより、別のブラウザーランタイムをインストールする必要がなくなります。 Internet Explorerは、ほぼ20年前にHTMLアプリケーションで同様のことを行いました。 もう1つの例はReactNativeで、利用可能な場合はOSのネイティブJSエンジンを使用します。 JavaScriptベースのアプリの場合、React Native for Windowsのようなものは、ネイティブUIウィジェットを使用するため、よりネイティブに感じられるため、Webテクノロジーではなくおそらく未来です。

@ Daniel15

(...)「ベアメタル」はどれくらい低レベルですか? マシンコード? アセンブリ言語? C? C ++? C#?

機械語にコンパイル可能な言語( source -> ELF/PEカウントされる)は、このコンテキストでは「ベアメタル」と見なされるため、ここでは抽象化レイヤーは重要ではありません。

Internet Explorerは、ほぼ20年前にHTMLアプリケーションで同様のことを行いました。

mshta.exe 90年代からsystem32に存在するmshtml.dllを使用させるのと「似たようなもの」。

もう1つの例はReactNativeで、利用可能な場合はOSのネイティブJSエンジンを使用します。 JavaScriptベースのアプリの場合、React Native for Windowsのようなものは、ネイティブUIウィジェットを使用するため、よりネイティブに感じられるため、Webテクノロジーではなくおそらく未来です。

デスクトップJSアプリで高いパフォーマンスが必要な場合は、十分な時間を持っている人がLLVMのフロントエンドを作成する必要があります。
コードの任意のスニペットを実行する機能が失われますが、それはセキュリティの観点からは利点になります。

/糸

この糸を脱線させてくれませんか? これは、カーソルが点滅する特定のパフォーマンスの問題に関する問題であり、JSベースのデスクトップアプリを開発することの一般的なメリットについて議論する場所ではありません。

あなたはこれらの暴言に興味のない人々のメールボックスをスパムしているだけです。

<input type=text>を2px * 10pxのサイズで、カーソルを置いた場所に配置してはどうでしょうか。 そうすれば、 <input> :P <blink></blink>のネイティブの点滅カーソルを使用します👍

また、この問題がどれほど深刻かはわかりません。VSCodeがアイドル状態のとき(コードを記述していないとき)、ほとんどの場合、フォーカスが合っておらず、フォーカスは他のアプリケーションにあります。カーソルの点滅が止まります。

私の経験から、gifはあまり良くありません。 私はかつてgif画像としてローディングスピナーを持っていました。 indexeddbとのやり取り中に使用しました。 デスクトップ上でも、スピナーが停止するのが見えることがありました。

ターミナルカーソルの変更をマスターとリリース/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ビルドに含まれており、数日中にリリースされるAprilStableビルドで利用できるようになります。 私たちのテスト結果を確認していただければ幸いです。 問題が発生した場合は、新しい問題を作成してください。

@rebornix 「または」 terminal.integrated.cursorBlinkingがtrue設定されているという意味ですか? それとも「and」は意図的なものでしたか?

@jedmao訂正してくれてありがとう、 orはずです。

このページは役に立ちましたか?
0 / 5 - 0 評価