メモリ リミッター

Android 17 以降では、メモリ リミッターをサポートしています。これは、Linux cgroup v2 を使用してアプリ プロセスのメモリ使用量をモニタリングし、制限するシステム サービスです。メモリ リミッターは、個々のアプリが過剰なシステムメモリを消費するのを防ぎます。これにより、システム全体のメモリ負荷が軽減され、重要なプロセスがメモリ不足(OOM)で強制終了されるのを防ぎます。

メカニズム

メモリ制限ツールは、Activity Manager Service(AMS)と統合して、プロセスのライフサイクル イベントと状態の変化を追跡します。メモリ制限ツールは、Linux カーネルの cgroup v2 ファイル システムを使用してメモリ制限を適用します。

メモリ制限機能を使用するには、デバイスのカーネルが cgroup v2 と memory コントローラをサポートしている必要があります。このサービスは、特に次の属性に依存しています。

memory.high
ソフトリミット。この上限を超えると、プロセスはスロットリングされ、カーネルはプロセスからメモリを再利用しようとします。
memory.swap.max
プロセスで使用できるスワップ領域の量を制限します。

アプリへの影響

メモリ上限を超えないアプリは、メモリ制限の影響を受けません。

アプリが memory.high の上限を超えると、カーネルはアプリのファイル バックアップ メモリを削除し、匿名メモリをスワップして、アプリを上限内に維持します。削除とスワップの結果、アプリの実行速度が低下する可能性があります。

極端な場合、アプリが匿名メモリの割り当てを続け、デバイスのスワップ領域が不足すると、アプリがメモリの割り当てに失敗し、クラッシュする可能性があります。

プロセスのモニタリング

メモリ制限ツールは、デフォルトでアプリプロセス(UID >= 10000)をモニタリングします。システム プロセスは、コア システムの安定性を検証するために、通常は除外されます。

メモリ リミッターは、プロセスの状態に基づいてメモリ上限を割り当てます。

  • 可視プロセスは、フォアグラウンド アクティビティ、フォアグラウンド サービス、その他のジャンクを検知できる状態など、ユーザーが検知できるプロセスです。

  • 表示されないプロセスは、ユーザーとやり取りしたり、ユーザーに表示されたりしないバックグラウンド プロセスです。

次の表に、特定のプロセス状態とメモリ上限の対応を示します。

プロセスの状態メモリ上限
PERSISTENT制限なし
PERSISTENT_UI制限なし
TOP表示
BOUND_TOP表示
FOREGROUND_SERVICE非表示
BOUND_FOREGROUND_SERVICE非表示
IMPORTANT_FOREGROUND表示
IMPORTANT_BACKGROUND非表示
TRANSIENT_BACKGROUND非表示
BACKUP非表示
SERVICE非表示
RECEIVER非表示
TOP_SLEEPING表示
HEAVY_WEIGHT非表示
HOME非表示
LAST_ACTIVITY非表示
CACHED_ACTIVITYキャッシュ済み
CACHED_ACTIVITY_CLIENTキャッシュ済み
CACHED_RECENTキャッシュ済み
CACHED_EMPTYキャッシュ済み

キャッシュされた状態では、プロセスがフリーズされ、最大限に再利用されます。

プロセスが割り当てられた memory.high 上限を超えると、メモリ リミッターがイベントを検出し、メモリ プロファイルのキャプチャや statsd への異常のロギングなどのデバッグ アクションをトリガーできます。

構成

vendor パーティションにある XML ファイルを使用して、メモリ リミッターを構成します。構成により、デバイスの特定のメモリ制約に基づいて絶対メモリ上限を調整できます。

  • ファイルパス: /vendor/etc/memory-limiter-config.xml

  • デフォルトの構成: 構成ファイルが見つからない場合、または読み取り不能か無効な場合、メモリ制限は無効になります。

XML 形式

構成ファイルは、memory-limiter-config.xsd で定義されたスキーマに準拠しています。このファイルでは複数の制限セットを定義できます。サービスは、デバイスの利用可能な RAM に基づいて最適な一致を選択します。すべてのメモリ値はメビバイト(MiB)単位で定義されます。

<MemoryLimiterConfig>
  <version>1</version>
  <configList>
    <limitSet>
      <!-- Limits for a phone with at least 14G of ram: 8G/4G/4G/4G -->
      <minimumRequiredMemTotal>14336</minimumRequiredMemTotal>
      <memVisible>8192</memVisible>
      <memNotVisible>4096</memNotVisible>
      <swapVisible>4096</swapVisible>
      <swapNotVisible>4096</swapNotVisible>
    </limitSet>
  </configList>
</MemoryLimiterConfig>
version
構成バージョンを識別する正の整数。これは 1 にする必要があります。
minimumRequiredMemTotal
この上限セットが有効になるために必要な最小の利用可能なシステム メモリ。
memVisible
可視プロセスに許可されるメモリ上限(memory.high)。
memNotVisible
表示されないプロセスに許可されるメモリ上限(memory.high)。
swapVisible
表示されているプロセスに許可されるスワップ上限(memory.swap.max)。
swapNotVisible
表示されないプロセスに許可されるスワップ上限(memory.swap.max)。

構成を変更する

システム全体の制限を変更する手順は次のとおりです。

  1. /vendor/etc/memory-limiter-config.xml を変更します。
  2. 変更を有効にするには、デバイスを再起動するか、system_server を再起動します。

シェルコマンド

am memory-limiter コマンドを使用すると、ユーザーとデベロッパーは開発とテストのために実行時にサービスを操作できます。

am memory-limiter <SUB-COMMAND>

ステータス

status サブコマンドは、メモリ制限ツールの動作ステータスを報告します。

adb shell am memory-limiter status

出力例:

Memory limiter
  enabled                  monitoring=true          ignored=none
  visibleMem=1948MB        visibleSwap=974MB
  notVisibleMem=974MB      notVisibleSwap=487MB
  started=36               watched=36               watch-failed=0
  events=0                 processes=36             process-hwm=36

出力のキーフィールドは次のとおりです。

monitoring
リミッターがプロセスをアクティブに監視しているかどうかを示します。
visibleMemnotVisibleMem
各状態の計算された絶対メモリ上限を示します。
events
プロセスが上限を超えた回数。
processes
モニタリング対象のプロセスの数。

無視

ignore サブコマンドは、UID またはすべてのプロセスを制限から一時的に除外します。このアクションは、パフォーマンス テストを行う場合や、特定アプリが上限を超過することを許可する場合に便利です。

adb shell am memory-limiter ignore 10087  // Ignore a specific UID
adb shell am memory-limiter ignore all    // Ignore all processes (effectively disables limiting)
adb shell am memory-limiter ignore none   // Resume normal operation

手動

manual サブコマンドは、特定のプロセス(プロセス ID または PID)の計算された上限を、カスタムの絶対値(MB 単位)でオーバーライドします。

adb shell am memory-limiter manual 1234 1024   // Set a 1024 MB limit for PID 1234
adb shell am memory-limiter manual 1234 none // Remove the manual override for PID 1234

手動オーバーライドは、プロセスのライフサイクルにのみ適用されます。プロセスが再起動すると、状態に基づいてデフォルトの上限に戻ります。