この記事では、Chrome 91 で導入された Memory Inspector について説明します。ArrayBuffer、TypedArray、DataView、Wasm メモリを検査できます。
はじめに
ArrayBuffer のデータを理解したいと思ったことはありませんか?Memory Inspector が登場する前は、DevTools では ArrayBuffers について限られた分析情報しか得られませんでした。デバッグ セッション中の [Scope] ビューからの検査は配列バッファ内の 1 つの値のリストに限られていたため、データ全体を把握することが困難でした。たとえば、下の例では、[Scope] ビューに配列の展開可能な範囲としてバッファが表示されます。
バッファ内の特定の範囲に移動するのは困難であり、最終的にそのインデックスに到達するまでにユーザーが下にスクロールする必要があった。しかし、たとえ掲載順位への移動は簡単であっても、このように実際に値をinspectingするのは面倒です。これらの数値の意味を理解するのは困難です。特に、32 ビット整数など、単一バイトとして解釈すべきでない場合はどうなるでしょうか。
Memory Inspector を使用して値を検査する
Chrome 91 には、配列バッファを検査するツールである Memory Inspector が導入されています。バイナリデータを表示するメモリ インスペクション ツールをご覧になったことがあるかもしれません。バイナリ コンテンツをそのアドレスとともにグリッド形式で表示し、基礎となる値をさまざまな方法で解釈できるメモリ インスペクション ツールをご覧になったことがあるかもしれません。これが Memory Inspector で実現する機能です。Memory Inspector を使用すると、コンテンツを表示したり、コンテンツを操作したり、現在の値の解釈に使用するタイプを選択したりできるようになります。バイトのすぐ横に ASCII 値が表示され、ユーザーが別のエンディアンを選択できるようになっています。Memory Inspector の実際の動作は次のとおりです。
お試しになる場合は、Memory Inspector を開いて配列バッファ(または TypedArray、DataView、Wasm Memory)を表示する方法と、その使用方法について詳しくは、Memory Inspector のドキュメントをご覧ください。こちらのサンプル(JS、Wasm、C++ 用)をお試しください。
Memory Inspector の設計
このパートでは、Memory Inspector が Web Components を使用してどのように設計されているかを確認し、設計目標の一つとその実装方法を示します。詳細については、Memory Inspector の設計に関するドキュメントをご覧ください。
Jack が、Web Components を使用して UI コンポーネントを作成する方法に関する社内ガイドを公開している、ウェブ コンポーネントへの移行に関するブログ投稿をご覧になったことがあるかもしれません。Web Components への移行は Google の Memory Inspector での作業と重なり、Google は新しいシステムを試すことにしました。次の図は、Memory Inspector を作成するために構築したコンポーネントを示しています(社内では Linear Memory Inspector と呼んでいます)。
LinearMemoryInspector
コンポーネントは、Memory Inspector のすべての要素を構成するサブコンポーネントを組み合わせた親コンポーネントです。基本的には Uint8Array
と address
を受け取り、いずれかが変更されるたびにデータを子に伝播し、再レンダリングをトリガーします。LinearMemoryInspector
自体は、次の 3 つのサブコンポーネントをレンダリングします。
LinearMemoryViewer
(値を表示)、LinearMemoryNavigator
(ナビゲーションを許可する)LinearMemoryValueInterpreter
(基になるデータのさまざまな型解釈を示します)
後者はそれ自体が親コンポーネントであり、ValueInterpreterDisplay
(値を表示する)と ValueInterpreterSettings
(ディスプレイに表示する型の選択)をレンダリングします。
各コンポーネントは、必要に応じてコンポーネントを再利用できるように、UI の小さなコンポーネントを 1 つだけ表現するように設計されています。コンポーネントに新しいデータが設定されるたびに再レンダリングがトリガーされ、コンポーネントに設定されたデータに変更が反映されます。以下に、コンポーネントを使用したワークフローの一例を示します。ここでは、ユーザーがアドレスバーの住所を変更すると、新しいデータ(この場合は表示する住所)が設定され、更新がトリガーされます。
LinearMemoryInspector
は自身を LinearMemoryNavigator
のリスナーとして追加します。addressChanged
関数は、address-changed
イベントでトリガーされます。ユーザーが住所入力を編集するとすぐに、addressChanged
関数が呼び出されるように前述のイベントが送信されます。この関数は住所を内部に保存し、data(address, ..)
セッターを使用してサブコンポーネントを更新するようになりました。サブコンポーネントは、その住所を内部で保存し、ビューを再レンダリングして、その特定の住所のコンテンツを表示します。
設計の目標: バッファサイズから独立したパフォーマンスとメモリ消費を実現する
Memory Inspector の設計時に念頭に置いた点の一つは、Memory Inspector のパフォーマンスをバッファサイズに依存させないようにすることでした。
前の部分で説明したように、LinearMemoryInspector
コンポーネントは UInt8Array
を受け取って値をレンダリングします。同時に、Memory Inspector はデータの一部のみを表示するため、Memory Inspector はデータ全体を保持する必要がないようにしたいと考えました(たとえば、Wasm Memory は 4 GB の大きさになることがあり、Memory Inspector に 4 GB を保存するのは避けたいものです)。
そこで、Memory Inspector の速度とメモリ消費量を、表示されている実際のバッファから切り離すために、LinearMemoryInspector
コンポーネントが元のバッファのサブ範囲のみを保持するようにします。
これを機能させるには、LinearMemoryInspector
が memoryOffset
と outerMemoryLength
という 2 つの引数を追加で取る必要があります。memoryOffset
は、渡された Uint8Array の開始点を示すオフセットで、正しいデータアドレスをレンダリングするために必要です。outerMemoryLength
は元のバッファの長さで、表示可能な範囲を把握するために必要です。
この情報により、実際にすべてのデータを配置しなくても、以前と同じビュー(address
周辺のコンテンツ)をレンダリングできます。それでは、異なる範囲にある別のアドレスがリクエストされた場合、どのように対処すればよいでしょうか。その場合、LinearMemoryInspector
は RequestMemoryEvent
をトリガーし、保持されている現在の範囲を更新します。以下に例を示します。
この例では、ユーザーがメモリページに移動すると(Memory Inspector はデータのチャンクを表示するためにページングを使用しています)、これにより PageNavigationEvent
がトリガーされ、それによって RequestMemoryEvent
がトリガーされます。このイベントにより新しい範囲の取得が開始され、その後、データを設定して LinearMemoryInspector
コンポーネントに伝播されます。そのため、新たに取得されたデータを表示しています。
ところで、実は知っていましたか?Wasm と C/C++ コードでメモリを検査することもできます
Memory Inspector は、JavaScript の ArrayBuffers
で利用できるだけでなく、C/C++ の参照/ポインタが指す Wasm メモリとメモリの検査にも使用できます(DWARF 拡張機能を使用します。まだ試していない場合はお試しください)。最新のツールを使用して WebAssembly をデバッグするをご覧ください。ウェブ上の C++ のネイティブ デバッグを行う Memory Inspector の概要を以下に示します。
おわりに
この記事では、Memory Inspector を紹介し、その設計の一例も紹介しました。ArrayBuffer の状況を理解するうえで Memory Inspector がお役に立てば幸いです。もしよろしければ、ぜひお知らせください。また、バグを報告してください。
プレビュー チャネルをダウンロードする
Chrome Canary、Dev、Beta を既定の開発ブラウザとして使用することをご検討ください。これらのプレビュー チャンネルでは、最新の DevTools 機能にアクセスしたり、最先端のウェブ プラットフォーム API をテストしたり、ユーザーが実際に体験する前にサイト上の問題を検出したりできます。
Chrome DevTools チームへのお問い合わせ
投稿内の新機能や変更点、または DevTools に関するその他のことについて話し合うには、次のオプションを使用します。
- crbug.com からご提案やフィードバックをお送りください。
- DevTools の問題を報告するには、DevTools でその他のオプション アイコン > [ヘルプ] > [DevTools の問題を報告する] を選択します。
- @ChromeDevTools にツイートします。
- 「DevTools の新機能」の YouTube 動画または DevTools のヒントの YouTube 動画でコメントを残してください。