1
誰もがこの予期しないV8 JavaScriptパフォーマンス動作を説明できますか?
更新(2020年3月2日) ここでの私の例のコーディングは、V8 JavaScriptエンジンの既知のパフォーマンスの崖から落ちるように正しい方法で構成されていることがわかります... 詳細については、bugs.chromium.orgに関する議論を参照してください。このバグは現在取り組んでおり、近い将来に修正される予定です。 アップデート(2020年1月9日) 以下で説明するように動作するコーディングを単一ページのWebアプリに分離しようとしましたが、そうすると、動作が消えました(??)。ただし、以下に説明する動作は、完全なアプリケーションのコンテキストではまだ存在します。 とはいえ、私はフラクタル計算コーディングを最適化しており、この問題はライブバージョンでは問題ではなくなりました。誰かが興味を持っているなら、この問題を明らかにするJavaScriptモジュールはまだここで利用可能です 概観 ブラウザベースのJavaScriptとWebアセンブリのパフォーマンスを比較するための小さなWebベースのアプリを完成させました。このアプリはマンデルブロ集合の画像を計算し、その画像の上にマウスポインターを移動すると、対応するジュリア集合が動的に計算され、計算時間が表示されます。 JavaScript(「j」を押す)またはWebAssembly(「w」を押す)の使用を切り替えて、計算を実行し、ランタイムを比較できます。 ここをクリックして、動作するアプリを確認してください ただし、このコードを作成する際に、予期しない奇妙なJavaScriptパフォーマンス動作がいくつか見つかりました... 問題の概要 この問題は、ChromeとBraveで使用されているV8 JavaScriptエンジンに固有のようです。この問題は、SpiderMonkey(Firefox)またはJavaScriptCore(Safari)を使用するブラウザでは発生しません。チャクラエンジンを使用しているブラウザでこれをテストできませんでした このWebアプリのすべてのJavaScriptコードはES6モジュールとして記述されています function新しいES6矢印構文ではなく、従来の構文を使用してすべての関数を書き直してみました。残念ながら、これはそれほど大きな違いはありません パフォーマンスの問題は、JavaScript関数が作成されるスコープに関連しているようです。このアプリでは、2つの部分関数を呼び出し、それぞれが別の関数を返します。次に、これらの生成された関数を、ネストされたforループ内で呼び出される別の関数に引数として渡します。 forループが実行される関数と比較すると、ループは独自のスコープに似たものを作成しているように見えます(ただし、本格的なスコープはわかりません)。次に、このスコープ(?)の境界を越えて生成された関数を渡すと、負荷が高くなります。 基本的なコーディング構造 各部分関数は、マンデルブロ集合イメージ上のマウスポインターの位置のXまたはY値を受け取り、対応するジュリア集合を計算するときに反復される関数を返します。 const makeJuliaXStepFn = mandelXCoord => (x, y) => mandelXCoord + diffOfSquares(x, y) const makeJuliaYStepFn = mandelYCoord => (x, y) => mandelYCoord + (2 * x * y) これらの関数は、次のロジック内で呼び出されます。 ユーザーは、mousemoveイベントをトリガーするマンデルブロ集合の画像の上にマウスポインターを移動します …