Optimize JavaScript execution


📌この文書の翻訳はOptimize JavaScript executionで、誤訳、意訳がある可能性があります.このほか、ドキュメントの最後に他の参照も記録されています.

緒論


JavaScriptでは、スタイル、データのソート、検索などを直接操作することで、ビジュアル化された更新を作成できます.このJavaScriptの実行時間が長すぎるか、実行タイミングが悪い場合は、パフォーマンスの問題が発生する可能性があります.私たちはできるだけこの影響を最小限に抑えなければなりません.
私たちが作成したjavascriptコードは実際に実行されているコードとは異なるため、javascriptの性能を分析することは芸術に近い行為である可能性があります.モダンブラウザはJITコンパイラだけでなく、さまざまな最適化とテクニックを使用しているため、コードの動作を大きく変えています.
それでも、JavaScriptをよりよく実行するための明確な方法があります.
  • ビジュアル更新は、settimeoutおよびsetIntervalではなくRAFを使用する.
  • 実行時間が
  • より長いJavaScriptは、メインスレッドではなくWeb Workerで実行されます.
  • DOMが
  • 以上のフレーム間で変化する場合はmicro-taskを使用します.
  • 🤔 1番と同じストーリーrAFのコールバック関数がmicro-task queueでenqueueであり、複数のフレームでDOMが変化した場合、アニメーションの状況について話している可能性があります.rAFを使うという意味ですよね?
    ChromeのDevToolとJavaScript Profilerを使用して、
  • JavaScriptの影響を分析します.
  • 1.視覚更新は、settimeoutおよびsetIntervalではなくRAFを使用します。


    フレームの開始点でコールバック関数を呼び出すことで、rAFはFrame lossを最小限に抑える.
    /**
        * If run as a requestAnimationFrame callback, this
        * will be run at the start of the frame.
        */
    function updateScreen(time) {
        // Make visual updates here.
    }
    
    requestAnimationFrame(updateScreen);
    settimeoutまたはsetIntervalを使用してビジュアル化更新をしようとすると、コールバック関数はフレーム間隔のランダムポイントで呼び出されます.最悪の場合、次のフレームが現れる前に呼び出され、フレームが失われる可能性があります.

    jQueryでは一時settimeoutを使ってアニメーションを作成していたが、バージョン3ではRAFの使用を開始した.古いバージョンのjQueryを使用している場合は、rAFを使用しているバージョン3に更新することを強くお勧めします.
    🤔 settimeoutまたはsetIntervalのコールバック関数の実行速度がモニタのリフレッシュ率よりも速い場合は、Frame Lossの原因にもなります.例えば、16.7ミリ秒のフレーム間隔を有するディスプレイ上でsettimeoutが4.7ミリ秒で呼び出されると、4回呼び出されても3回の損失を招く可能性がある.
    ただし、rAFの場合、呼び出し時間はディスプレイのリフレッシュレートによって決まるので、上記のフレームが失われる心配がなく、再描画前に呼び出されることを確保する必要がない.

    2.実行時間の長いJavaScriptは、メインスレッドではなくWeb Workerで実行されます。


    JavaScriptは、ブラウザのmainthread上で実行され、スタイル計算、レイアウト、塗装の順に実行されます.JavaScriptの実行時間が長すぎると、以降のタスクが順次ブロックされ、フレームが失われる可能性があります.
    JavaScriptをいつ実行するか、どのくらいの時間で実行するかを戦略的に理解する必要があります.スクロール(?)アニメーションが存在する場合、JavaScriptの実行時間は理想的には3~4ミリ秒です.この時間より長い場合、フレームが失われる可能性があります.暇な時間にいると、もっと暇な時間ができます.(動画をスクロールする内容のようですが説明できません)
    DOM(データ操作、ナビゲーション、ソートなど)にアクセスしない場合は、計算タスクをWeb Workerに渡すことができます.
    var dataSortWorker = new Worker("sort-worker.js");
    dataSortWorker.postMesssage(dataToSort);
    
    // The main thread is now free to continue working on other things...
    
    dataSortWorker.addEventListener('message', function(evt) {
        var sortedData = evt.data;
        // Update data on screen...
    });
    Web WorkerにはDOMアクセス権限がないため、DOMにアクセスする必要があるタスクをWeb Workerに渡すことは無効です.(😥説明が難しい)メインスレッド上で作業する必要がある場合は、大きなタスクをマイクロタスクに分割し、各タスクにかかる時間が数ミリ秒を超えず、各フレームワークでRequestAnimationFrameプロセッサを実行するバッチ処理方法を考えてください.
    この方法を使用する場合は、ユーザーに進捗状況を表示し、操作中であることを通知する必要があります.いずれにしても、この方法はアプリケーションのmainthreadをより自由にし、応答性を向上させるのに役立ちます.
    🤔 レンダラープロセス内の複数のスレッドでは、イベントやレンダリングを担当するmainthreadが重くなるのを防ぐために、WebWorkerを使用してJavaScriptの複雑な演算を別のthreadから並列に処理することができます.そこまで理解すればいい詳細については、次のドキュメントを参照してください.
    Web Worker
    ブラウザプロセス
    Minimize main thread work
    Main Thread

    3.フレームワークの作成に必要なJavaScriptコストの決定


    フレームワーク、ライブラリ、またはコードを評価する際には、各フレームワークがJavaScriptを実行するコストを評価することが重要です.これは、パフォーマンスに致命的な影響を及ぼす可能性のあるトランジションまたはスクロールアニメーションにとって非常に重要です.
    Chrome DevToolsは、これらのJavaScriptのコストを測定するのに役立ちます.

    ここで、Main SectionはJavaScript呼び出しにFlame Chartを提供しているので、どのような関数が呼び出され、どのくらい実行されたかを簡単に知ることができます.
    これらの情報に基づいて、JavaScriptがパフォーマンスに与える影響をアプリケーションで確認し、実行に時間がかかる関数を検索および変更できます.前述したように、実行時間の長いJavaScriptを削除するか、不可能な場合はWeb Workerに移動する必要があります.

    4.JavaScriptを小さな単位に最適化しない


    オブジェクトのオフセット上限を求めるのはgetBoundingClientRectの計算より100倍ほど速いことを知っていますか?これを知っていればもっと良いかもしれませんが、これらの関数はフレームごとに呼び出される回数が非常に少なく、これらのコストを節約してもミリ秒しかかかりません.あまりにも小さな最適化では、効率が低下する可能性があります.
    ゲームなどのアプリケーションの計算コストが高い場合は、フレームごとに多くの計算が含まれているため、これらの推奨は例外です.

    rAFの詳細について


    CPUリソース(CPU Optimization)を考慮する.別のタブでは、RAFのコールバック関数の呼び出しが停止します.

    settimeout/setIntervalの機能

  • はCPUリソースを考慮しない.コールバック関数は、他のタブでも実行されます.
  • setIntervalの場合、コールバック関数の実行時間が遅延を超えた場合、タスクキューで待機しているコールバック関数が多すぎます.
  • What requestAnimationFrame is ?
    Why requestAnimationFrame is better than setTimeout and setInterval in HTML5
    Window.requestAnimationFrame