高度なアプリケーションでのメモリ使用量

このトピックでは、高度なアプリケーションでのメモリ使用量について詳しく説明します。 リアルタイム対応アプリケーション (RTApps) で使用可能なメモリの詳細については、「 メモリと待機時間の管理に関する考慮事項 」を参照してください。

高度なアプリケーションは、次のメモリとストレージにアクセスできます。

  • 高レベル コア上の 256 KiB の RAM で、高レベル アプリケーション専用として完全に確保されています。 この領域の最大 1 KiB は、上位レベルのアプリケーションと RTApps が通信する共有バッファー チャネルごとに割り当てられます。
  • 1 MiB 読み取り専用フラッシュ メモリ。高レベルコアとリアルタイム コア間で共有されます。
  • 読み取り/書き込み (変更可能) ストレージ。デバイスの再起動時に保持されます。 変更可能ストレージの詳細については、「 Azure Sphere」を参照してください。

Note

フラッシュを繰り返し更新すると、最終的にフラッシュが摩耗し、無効になります。 そのため、フラッシュの不要な更新を避けるためにコードを設計する必要があります。 たとえば、再起動後に保存された状態を回復できるように、終了する前にアプリケーションの状態を保存する場合は、状態が変更された場合にのみ、アプリケーションの状態をフラッシュに保存することを検討してください。

フラッシュ メモリの使用量を決定する

フラッシュ メモリの使用量を判断するには、イメージ メタデータ、アプリケーション マニフェスト、実行可能イメージを含むイメージ パッケージ ファイルのサイズのみを考慮してください。 Azure Sphere OS や、周辺機器を制御し、Azure IoT Hubへの接続を有効にするランタイム サービスや共有ライブラリなど、Microsoft提供のコンポーネントで必要なストレージを考慮する必要はありません。 同様に、アプリケーションの完全バックアップ コピーのサイズや、破損や空の更新に関する問題が発生した場合にフェールオーバーまたはロールバックを有効にするコンポーネントを含める必要はありません。

ただし、開発中とデバッグ中は、デバッガーのサイズは制限に対してカウントされます。 デバッガーは az sphere device enable-development によって自動的に追加され、[az sphere device enable-cloud-test]( によって削除されます。/reference/az sphere-device.md)。 SDK で使用されるデバッガーのサイズを確認するには、Microsoft Azure Sphere SDK インストール ディレクトリの DebugTools フォルダーで gdbserver.imagepackage を検索します。

アプリケーション イメージ パッケージとデバッガー (存在する場合) が 1 MiB の合計制限を超えた場合、 az sphere device sideload コマンドはエラーを返します。 az sphere image add --image コマンドは、イメージ パッケージが 1 MiB を超えると、新しいイメージを Azure Sphere カタログにアップロードしてもエラーを返します。

256 KiB RAM の制限は、アプリケーションだけに適用されます。デバッガーで使用される RAM を許可する必要はありません。 追加のメモリはカーネル割り当て用に予約されています。

現在のAzure Sphere チップ (MT3620) 用に書き込まれたアプリケーションでは、使用可能なフラッシュと RAM が増加する可能性があります (ただし、減少することはありません)。 将来のAzure Sphere チップの制限は異なる場合があります。

メモリ不足状態

アプリケーションで使用する RAM が多すぎる場合、Azure Sphere OS は SIGKILL シグナルで終了します。 たとえば、デバッガーでは次のような内容が表示されます。

Child terminated with signal = 0x9 (SIGKILL)

SIGKILL シグナルは、SIGTERM 要求を受け取った後に上位レベルのアプリケーションが終了に失敗した場合にも発生します。 詳細については、 アプリケーションのライフサイクルを 参照してください。

メモリ不足の状態によるアプリケーションのクラッシュを回避するには、 上位レベルのアプリケーションで RAM 使用率を管理するためのベスト プラクティスを参照してください。

ランタイム アプリケーションの RAM 使用率を決定する

Azure Sphereには、実行時にメモリ使用量情報を取得するための関数がいくつか用意されています。 これらを使用すると、高レベルのアプリケーションのメモリ使用量を監視できます。これにより、メモリ使用量が 256 KiB の制限内で指定したしきい値を超えた場合に、アプリケーションを安全に再起動できます。 使用できる関数は次の通りです:

  • Applications_GetTotalMemoryUsageInKB: メモリ使用量の合計 (kibibytes) を取得します。 これは、アプリまたはデバッグ サーバーに代わってカーネルの割り当て (ソケットのバッファーなど) を含め、(KiB で) 生の値として返される、システム上のアプリの物理メモリ使用量の合計です。
  • Applications_GetUserModeMemoryUsageInKB: ユーザー モードのメモリ使用量を kibibytes で取得します。 これは、アプリによって直接使用される物理メモリの量、その代わりに任意のライブラリによって使用されるメモリ ( アノン 割り当てとも呼ばれます)、デバッグ サーバーによって使用されるメモリ (KiB) として生の値として返されます。
  • Applications_GetPeakUserModeMemoryUsageInKB: ユーザー モードのメモリ使用量のピークを kibibytes 単位で取得します。 これは、現在のセッションで使用されるユーザー メモリの最大量です。 アプリケーションのメモリ使用量をテストするときは、この値が 256 KiB を超えないようにする必要があります。 この値は、アプリが再起動または再デプロイされるたびにリセットされます。 この関数を使用して、アプリケーションが推奨される 256 KiB の制限にどの程度近づいているかをおおよそ確認します。

これらの関数を高度なアプリケーションで使用するには、applications.h ヘッダー ファイルを含めます。 開発中にこれらの関数を使用して、アプリケーションの全体的なメモリ使用量を把握できますが、ログと共に使用 して、フィールド内のデバイスから情報をキャプチャすることもできます。 Memory Overuse Detection and Cleanup スニペットは、予期しないメモリ使用量を検出して適切に処理する方法を示しています。

Note

これらの関数は、OS から見たメモリ使用量を返します。 現在、アプリケーションによるユーザー ヒープの割り当てによるメモリの解放は、これらの関数では報告されません。 メモリは今後使用するために malloc ライブラリに返されますが、OS 自体によってメモリが割り当てられ解放されない限り、OS によって報告される統計情報は変更されません。 たとえば、ソケットにメモリを割り当てる場合があります。 したがって、これらの関数は、アプリケーションが保守的に動作して信頼性を最大限に高めるのに役立つ最悪のシナリオを理解するのに役立ちます。 値は概数であり、OS のバージョンによって異なる場合があります。

ヒープ メモリの割り当て追跡を追加する

ヒープ メモリ割り当ての追跡を追加することで、追加のメモリ使用量情報を取得できます。これは、静的および動的にリンクされたライブラリによって行われているユーザーとカーネルの割り当てを示します。 これにより、メモリを最も効果的に使用できるように、アプリケーションでメモリが使用されている場所をより詳細に把握できます。 この機能は、Azure Sphere OS バージョン 21.07 以降およびアプリケーション ランタイム バージョン (ARV) 10 以降で利用可能であり、開発対応が有効なデバイスでのみ動作し、アプリケーションがデバッガー下で実行されていない場合にのみ機能します。

Note

ヒープ メモリ割り当ての追跡を正しく機能させるには、このセクションで説明する両方の構成タスクを完了する必要があります。 失敗した場合、コンパイル中に警告が報告され、ヒープ メモリ情報は表示されません。

ヒープ メモリ割り当ての追跡を有効にするには、次の 2 つの操作を行う必要があります。

  • HeapMemStats 機能をアプリケーションの app-manifest.json ファイルに追加します。

      "Capabilities": {
        "HeapMemStats": true
      },
    
  • アプリケーションの CMakeLists.txt ファイルのDEBUG_LIB "libmalloc" コマンドにazsphere_target_add_imageを追加して、libmalloc ライブラリをイメージ パッケージに追加します。

    azsphere_target_add_image_package(${PROJECT_NAME} DEBUG_LIB "libmalloc")
    

Important

ヒープ メモリ割り当ての追跡は開発が有効なデバイスでのみ機能するため、デプロイ用のイメージ パッケージをビルドする前に、次の操作を行ってアプリケーションから削除する必要があります。

  • アプリケーションの app-manifest.json ファイルから行 '"HeapMemStats": true' を削除します。
  • アプリケーションの CMakeLists.txt ファイルの DEBUG_LIB "libmalloc" コマンドからazsphere_target_add_image_package(${PROJECT_NAME} DEBUG_LIB "libmalloc"を削除します。

Visual Studio パフォーマンス プロファイラーを使用する

Visual Studioを使用する場合は、そのパフォーマンス プロファイラー機能を使用して、アプリケーション のメモリ使用量に関する情報を取得できます。 このプロファイラーを使用するチュートリアルについては、Tutorials/MemoryUsage を参照してください。

前提条件

  • Azure Sphere SDK がインストールされたVisual Studioを実行している PC に接続されたAzure Sphere開発キット。 Windows 用 Azure Sphere SDK のインストールを参照してください。
  • 開発用に準備されたデバイス。 az sphere device enable-development を参照してください。 デバイスの開発が有効になっていない場合、パフォーマンス プロファイラーはデータを返しません。

メモリ使用量プロファイラーを起動する

  1. [デバッグ>パフォーマンス プロファイラー] を選択するか、Alt キーを押しながら F2 キーを押してパフォーマンス プロファイラーのスタート ウィンドウを開きます。

    Visual Studio パフォーマンス プロファイラー ウィンドウ

  2. Analysis Target で、Azure Sphere Device Profiler が表示されない場合は、Choose Target を選択し、Azure Sphere Device Profiler を選択します。

  3. Available Tools で、Azure Sphere Memory Usage がオンになっていることを確認し、Start を選択してメモリ使用量プロファイリング ウィンドウを開き、メモリ プロファイラーを起動します。

  4. アプリケーションを展開または再起動する必要がある場合は、[ デバッグ>デバッグなしで開始 ] を選択するか、 Ctrl キーを押しながら F5 キーを押してアプリケーションをデバイスに展開します。

    Important

    アプリケーションの正確な RAM 使用状況情報を取得するには、[デバッグ なしで アプリを起動する](buid-hl-app.md#build-and-deploy-the-application-in-visual-studio-without-debugging) することが重要です。 デバッガーでアプリを実行すると、デバッグ サーバーによって消費されるメモリが報告された RAM 使用率の統計情報に含まれるため、RAM 使用率が増大します。

メモリ使用量プロファイラー データの解釈

メモリ使用量プロファイル ウィンドウには、次のようなビューが表示されます。

Visual Studioメモリ使用量プロファイラー ウィンドウ

ビューの中央に、Azure Sphere デバイス物理メモリ グラフには、アプリの実行中に 3 つの異なる RAM 使用状況統計情報 (最も近い KiB に表示) が 3 つの異なる行としてプロットされます。

  • 合計: アプリまたはデバッグ サーバーに代わってカーネル割り当て (ソケットのバッファーなど) を含む、システム上のアプリの物理メモリ使用量の合計。
  • ユーザー: アプリによって直接使用される物理メモリの量、その代わりに任意のライブラリによって使用されるメモリ ( アノン 割り当てとも呼ばれます)、およびデバッグ サーバーによって使用されるメモリ。
  • ピーク ユーザー: 現在のセッションで使用されるユーザー メモリの最大量。 アプリケーションのメモリ使用量をテストするときは、この値が 256 KiB を超えないようにする必要があります。 追加のメモリはカーネル割り当て用に予約されています。 この値は、アプリが再起動または再デプロイされるたびにリセットされます。

グラフには、(三角形で表される) New Peak イベントの発生もプロットされます。 このイベントは、ピーク時のユーザー メモリ使用量に対して新しい最大値が発生するたびに発生します。 このイベントは、スクリーン リーダーのアクセシビリティに対して有効になっています。

ヒープ メモリ割り当ての追跡を有効にしていて、アプリケーションがデバッガーで実行されていない場合は、ヒープ メモリの統計情報を示す追加のグラフが表示されます。

  • 合計ヒープ: 静的ライブラリと動的ライブラリを含め、アプリケーションによって、またはアプリケーションに代わって割り当てられたヒープ メモリの合計。
  • 共有ライブラリ ヒープ: Azure Sphere OS によって提供される動的にリンクされたライブラリからの割り当て。

Visual Studio ヒープ メモリの使用量

グラフの上には、タイムライン ビューにアプリの実行時間が表示され、下のグラフ上のデータと関連付けられます。 [拡大][縮小] を使用して、特定の期間に着目できます。

グラフの下には、テーブル ビューに同じメモリ統計情報とイベントが表示されます。

Tip

テーブルからクリップボードにデータをコピーするには、 Ctrl キーを押しながら A キーを押してすべての行を選択し、 Ctrl キーを押しながら C キーを押します。

このセクションに示す最初の 2 つのグラフは、メモリ リークを含むメモリ使用量のチュートリアルの Stage 1 の実行中に作成されました。 メモリ使用量は各グラフで単調に上昇し、リークの視覚的証拠が提供されます。 メモリ使用量のチュートリアルのStage 2のように、リークが修正されると、メモリの割り当てと割り当てが解除されるとグラフが上昇し、低下します。

Visual Studio でのメモリ リークを伴わないヒープ メモリ使用量

メモリ使用量の合計に関する統計情報を表示する

az sphere device app show-memory-stats コマンドは、接続されているデバイスで実行されているアプリケーションの合計メモリ使用量、ユーザー モード使用率、およびピーク ユーザー モード使用率に関するメモリ使用量の統計情報を返します。 デバイスには、このコマンドを実行するように appDevelopment デバイス機能が構成されている必要があります。

アプリの実行中に表示される RAM 使用率の統計情報は次のとおりです。

  • 合計 (カーネル + ユーザー モード):アプリまたはデバッグ サーバーに代わってカーネル割り当て (ソケットのバッファーなど) を含む、システム上のアプリの物理メモリ使用量の合計。
  • ユーザー モード: アプリによって直接使用される物理メモリの量、その代わりにライブラリによって使用されるメモリ ( アノン 割り当てとも呼ばれます)、デバッグ サーバーによって使用されるメモリ。
  • ピーク ユーザー モード: 現在のセッションで使用されるユーザー メモリの最大量。 アプリケーションのメモリ使用量をテストするときは、この値が 256 KiB を超えないようにする必要があります。 追加のメモリはカーネル割り当て用に予約されています。 この値は、アプリが再起動または再デプロイされるたびにリセットされます。

ヒープ メモリ割り当ての追跡を有効にしていて、アプリケーションがデバッガーで実行されていない場合は、ヒープ メモリ統計の追加行が表示されます。

  • ヒープ: アプリ + 静的ライブラリ: コードおよびそれに静的にリンクされたライブラリからのカーネルとユーザーの割り当て。
  • Heap: <ダイナミック ライブラリの割り当て>: Azure Sphere OS によって提供される個々の動的にリンクされたライブラリからの割り当て。

メモリ使用量の継続的な監視

時間の経過に伴うメモリ使用量を監視するには、スクリプトを使用して [az sphere device app show-memory-stats]( を実行できます。/reference/az sphere-device.md) コマンドをループ内で実行します(次の例を参照)。

Windows コマンド プロンプト

メモ帳または別のテキスト エディターを使用して、次の内容で memuse.bat バッチ スクリプト ファイルを作成します。

@echo off

:loop
call az sphere device app show-memory-stats
choice /d y /t 1 > nul
goto loop

コマンド プロンプトで名前を入力してバッチ スクリプトを実行します (現在のディレクトリにない場合は、ファイルの完全なパス)。

C:\Users\username> memuse.bat
 -------------------------- -------------
 Name                       Usage (bytes)
 ========================================
 Total (Kernel + User Mode) 65536
 -------------------------- -------------
 User Mode                  36864
 -------------------------- -------------
 Peak User Mode             36864
 -------------------------- -------------
 -------------------------- -------------
 Name                       Usage (bytes)
 ========================================
 Total (Kernel + User Mode) 65536
 -------------------------- -------------
 User Mode                  36864
 -------------------------- -------------
 Peak User Mode             36864
 -------------------------- -------------

スクリプトを終了するには、コマンド プロンプト ウィンドウで Ctrl + C キーを押し、"バッチ ジョブの終了" プロンプトに Y と答えます。

Windows PowerShell

while ($true) {
    az sphere device app show-memory-stats
    Start-Sleep -Seconds 1
}

メモリ使用量とデバッガー

デバッガーでアプリを実行すると、報告されるメモリの統計情報には、デバッグ サーバー プロセスのメモリ使用量や、ブレークポイントの設定など、デバッグによって発生するその他のメモリ使用量も含まれます。 このため、正確なメモリ統計を収集しようとするときは、デバッグを行わずに常にアプリを実行する必要があります。

ただし、デバッガーでアプリを実行する場合は、メモリ使用量プロファイラーを使用すると便利です。 メモリ使用量の相対的な変化を観察しながら、ブレークポイントを設定し、コード行をステップ実行すると、メモリ使用量の急増やメモリ リークの原因を特定するのに便利な手法です。

Visual Studioでデバッグすると、パフォーマンス プロファイラーは自動的に開きますが、ヒープ メモリ割り当ての追跡は表示されません。