このサイトのコンテンツは、人工知能(AI)または機械翻訳技術を使用して翻訳されており、誤りが含まれている場合があります。

Skip to content

カルーセルの読み込みにおけるフロントエンドのメモリ使用量を30倍改善

2020年第2四半期、エクスペリエンスページの技術的なリファクタリングを行い、Reactへの書き換えとREST APIの導入を行いました。しかし、実装中に興味深い問題が見つかりました。

「体験」ページには約20個のカルーセルがあり、それぞれに少なくとも60個のタイルが含まれています。そのため、ページにはタイトル、ユーザー評価、同時接続ユーザー数、サムネイルなどの関連情報を含め、1,200件以上の体験が表示されることになります。各カルーセルでは、右側のスクロールボタンをクリックすると、さらに体験がある場合に次のバッチを読み込むリクエストが送信されます。 すると、リクエストによって取得された新しいデータがカルーセルに追加されます。つまり、DOMにノードが追加され、ブラウザ内でレンダリングされるサムネイルも増えることになります。ユーザーがスクロールしてさらにデータをリクエストするたびにブラウザ内のメモリ使用量は増加し、その結果、UXが低下して遅延が生じ始めます。

メモリプロファイル

この問題の分析には、Chrome デベロッパーツールを使用できます。最初のスナップショットはページの初期読み込み時に取得され、2番目のスナップショットはユーザーがカルーセル内の「次へ」ボタンを12回クリックした後に取得されます。100個以上の文字列ノードとサムネイルのレンダリング増加により、メモリ使用量が約9.7MB増加していることが確認できます。

解決策

カルーセルがスクロールする際、ユーザーにはカルーセルウィンドウ内のアイテムのみが表示されます。例えば、1920×1080解像度のノートパソコンでフルスクリーン表示のブラウザを使用する場合、一度に表示されるアイテムは最大で約9個です。したがって、表示されないノードやサムネイルをすべてレンダリングしたり、リクエストから返されたデータを余分にDOMに取り込んだりする必要はありません。

そこで、次のようなアイデアです。APIリクエストから生データを初めて取得した後、DOMへのレンダリングに備えて、表示領域と同じ長さの配列を作成します。このレンダリング用配列には、画面を埋め尽くし、次にスクロールするためのデータのみを格納します。配列の残りの部分は、表示ウィンドウがそこに近づくまで埋める必要はありません。 レンダリングデータの範囲を記録するために、2つのインデックス(renderingStartIndex と renderingEndIndex)を用意します。リスト内のどの開始位置が表示されているかを示すカーソルを設定します。スクロール時には、カーソルを常に最初の表示アイテムのインデックスに更新する必要があります。スクロールアニメーションが終了する前に、次のカーソルがレンダリングデータ配列の範囲内にあるかどうかを確認する必要があります。 カルーセルのウィンドウサイズとカードのサイズに基づけば、表示ウィンドウに収まる可視アイテムの数は容易に把握できます。次に、現在のウィンドウと次のウィンドウのアイテムが、レンダリングデータ配列の範囲内にあることを確認する必要があります。範囲外の場合は、生データからアイテムを取得して空のリストを埋める一方で、カーソル位置より前のデータをクリアします。これは、ユーザーが右または左にスクロールした際に適用されます。 ユーザーが右にスクロールする場合、バックグラウンドで追加のデータを取得することで、新しいデータを受け取るたびに生データを埋めていきます。ただし、生データはページのレンダリングには関与しません。

改善後の表示は以下の通りです:

メモリプロファイル

Chrome デベロッパーツールをもう一度見てみましょう。前回と同様、最初のスナップショットは初期化時に、2つ目は右に12回スクロールした後に取得されています。現在、100件以上のアイテムを読み込んでも、メモリ使用量の増加はわずか0.3MBにとどまっています。以前の9.7MBと比較すると、大幅な改善が見られます。

今後の予定

大規模なデータウィンドウに対応できるようカルーセルコンポーネントを改善するほか、機能やページをリファクタリングする際には、パフォーマンス情報を把握するためにベンチマークをさらに追加する必要があります。

現代のWebアプリケーションスタックはフロントエンドへと移行しつつありますが、フロントエンドのテレメトリを収集・改善することは、従来のバックエンドのテレメトリと同様に重要です。

Ying Jiangは、Robloxのプリンシパル・フロントエンド・ソフトウェア・エンジニアです。Roblox初のフロントエンド・エンジニアとして、最新のフロントエンド技術スタックをRobloxに導入し、開発およびデプロイメントのパイプラインを改善する業務に従事しています。また、チャット、通知ストリーム、ボイスなどのリアルタイム機能の開発にも携わってきました。

Roblox Corporationおよび本ブログは、いかなる企業やサービスについても推奨または支持するものではありません。また、本ブログに含まれる情報の正確性、信頼性、完全性について、いかなる保証や約束も行いません。