Electron と V8 メモリケージ
Electron 21 以降では V8 メモリケージが有効になり、一部のネイティブモジュールに影響を及ぼします。
Electron 21+ のネイティブモジュール使用に関する進行中の議論については、electron/electron#35801 をご覧ください。
Electron 21 では、Electron にて V8 のサンドボックス化ポインタ が有効になります。これは Chrome の Chrome 103 での同様の決定 に従ったものです。 これはネイティブモジュールにいくつかの影響を与えます。 ま た、以前には関連する技術である ポインタ圧縮 を Electron 14 で有効にしていました。 当時はあまり話題になりませんでしたが、ポインタ圧縮は V8 の最大ヒープサイズに影響を及ぼします。
この 2 つの技術を有効にすることで、セキュリティ、パフォーマンス、メモリ使用量に大きなメリットがあります。 しかし、それらを有効化するにあたっていくつかの欠点もあります。
サンドボックス化ポインタを有効にする主な欠点は、外部 ("ヒープ外") のメモリを指す ArrayBuffer が許可されなくなる ことです。 つまり、V8 でこの機能に依存しているネイティブモジュールは、Electron 20 以降でも引き続き動作するようにリファクタする必要があります。
ポインタ圧縮を有効にする主な欠点は、V8 ヒープのサイズが最大 4GB に制限される ことです。 正確な詳細は少し複雑です。例えば、ArrayBuffer は V8 ヒープの他の部分とは別にカウントされますが、それ自体の制限 はあります。
Electron のアップグレードのワーキンググループ は、ポインタ圧縮と V8 メモリケージのメリットはデメリットを上回ると考えています。 主な理由は次の 3 つです。
- Electron が Chromium に近づきます。 V8 の設定など複雑な内部の詳細について Electron が Chromium からあまる乖離しなければ、誤ってバグやセキュリティ上の脆弱性を導入する可能性は低くなります。 Chromium のセキュリティチームは侮れない素晴らしさであり、彼らの成果を確実に生かしたいのです。 さらに、あるバグが Chromium で使用されていない設定にしか影響しない場合、そのバグ修正は Chromium チームにとって優先されないでしょう。
- パフォーマンスが改善します。 ポインタ圧縮により、V8 ヒープサイズを最大 40% 削減し CPU と GC の性能を 5%-10% 向上させます。 Electron アプリケーションの大部分は、4GB のヒープサイズ制限にぶつかることはなく、外部バッファを必要とするネイティブモジュールも使用しないため、これらは性能面で大きなメリットとなります。
- よりセキュアになります。 Electron アプリの中には信頼できない JavaScript を実行しているものがあります (できれば セキュリティに関する推奨事項 に従ってください!)。そういったアプリでは V8 メモリケージを有効にすることで、V8 の厄介な脆弱性を持つ巨大クラスからそれらを保護できます。
最後に、どうしても大きなヒープサイズが必要なアプリのための回避策をご紹介します。 例えば、ポインタ圧縮を無効にしてビルドしたアプリに Node.js のコピーを同梱し、メモリ負荷の大きい作業を子プロセスに移行させることが可能です。 またやや複雑ではありますが、ポインタ圧縮を無効にしたカスタム版の Electron を作成することも可能です。その場合、特定のユースケースに対して別のトレードオフが必要になります。 そして最後に、そう遠くない将来、wasm64 により WebAssembly で構築されたアプリが 4GB を超える巨大なメモリをウェブと Electron の両方で利用できるようになる予定です。
FAQ
アプリがこの変更の影響を受けるかどうかは、どうすればわかりますか?
Electron 20 以降で外部メモリを ArrayBuffer でラップしようとすると、実行時にクラッシュします。
アプリでネイティブ Node モジュールを使用していない場合は安全です。純粋な JS からこのクラッシュを引き起こす方法はありません。 この変更は、V8 ヒープ外でのメモリ割り当て (例えば malloc
や new
の使用) を行い、その外部メモリを ArrayBuffer でラップしているネイティブ Node モジュールにのみ影響します。 これはかなり稀なユースケースですが、一部のモジュールではこの手法が使われており、そのようなモジュールは Electron 20 以降と互換性を持たせるためのリファクタが必要です。