1. ホーム
  2. java

[解決済み] Androidでアプリケーションのメモリ使用量を確認するにはどうすればよいですか?

2022-03-20 18:23:51

質問

Androidアプリケーションのメモリ使用量をプログラムで確認するにはどうしたらいいですか?

何か方法があればいいのですが。さらに、携帯電話の空きメモリも取得するにはどうすればいいのでしょうか?

解決方法は?

Linuxのような最新のOSでは、メモリ使用量は 極めて 複雑で理解しにくい分野です。 実際、どのような数字であっても、実際に正しく解釈できる可能性は極めて低いのです。 (私が他のエンジニアとメモリ使用量の数字を見るたびに、いつもその数字の意味について長い議論が交わされ、曖昧な結論にしかならない)。

注:現在、私たちは、より充実したドキュメントで アプリのメモリ管理 は、ここに書かれている内容の多くをカバーし、Androidの状態についてより最新である。

まず最初に、この記事の最後の部分を読んでください。Androidでメモリがどのように管理されているかについての議論があります。

Android 2.0からのサービスAPIの変更点

現在 ActivityManager.getMemoryInfo() は、全体的なメモリ使用量を見るための最高レベルのAPIです。 これは主に、システムがバックグラウンド・プロセス用のメモリを失い、サービスのような必要なプロセスを殺す必要が出てくるまでの時間を、アプリケーションが測定するのに役立つものです。 なぜなら、Javaのヒープ制限は、1つのアプリケーションがこの時点までシステムにストレスを与えることを避けるために存在する部分があるからです。

より低いレベルでは、Debug API を使用して、メモリ使用量に関する生のカーネルレベルの情報を取得することができます。 android.os.Debug.MemoryInfo

2.0 からは、API もあります。 ActivityManager.getProcessMemoryInfo を使用すると、別のプロセスに関するこの情報を取得することができます。 ActivityManager.getProcessMemoryInfo(int[])

このデータをすべて含む低レベルのMemoryInfo構造体が返されます。

    /** The proportional set size for dalvik. */
    public int dalvikPss;
    /** The private dirty pages used by dalvik. */
    public int dalvikPrivateDirty;
    /** The shared dirty pages used by dalvik. */
    public int dalvikSharedDirty;

    /** The proportional set size for the native heap. */
    public int nativePss;
    /** The private dirty pages used by the native heap. */
    public int nativePrivateDirty;
    /** The shared dirty pages used by the native heap. */
    public int nativeSharedDirty;

    /** The proportional set size for everything else. */
    public int otherPss;
    /** The private dirty pages used by everything else. */
    public int otherPrivateDirty;
    /** The shared dirty pages used by everything else. */
    public int otherSharedDirty;

しかし、何が違うのかというと Pss , PrivateDirty および SharedDirty ......さて、お楽しみはこれからです。

Android(とLinuxシステム全般)では、多くのメモリが実際には複数のプロセスで共有されています。 そのため、1つのプロセスがどれだけのメモリを使用しているかは、実際には明らかではありません。 さらに、ディスクへのページングアウト(Androidでは使っていないスワップは別として)を加えると、さらにわからなくなります。

したがって、各プロセスに実際にマッピングされている物理 RAM をすべて取り出して、すべてのプロセスを合計すると、おそらく実際の総 RAM よりもはるかに大きな数字になるはずです。

その Pss 基本的に、あるプロセスの RAM の各ページは、そのページを使用している他のプロセスの数の比率でスケーリングされます。 このようにして、(理論的には) すべてのプロセスの pss を合計して、それらのプロセスが使用している総 RAM を確認したり、プロセス間の pss を比較して、それらの相対的な重みを大まかに把握したりすることができるのです。

ここでもう1つ興味深い指標は PrivateDirty これは基本的に、ディスクにページングできず(ディスク上の同じデータによってバックアップされていない)、他のプロセスと共有されていない、プロセス内部のRAMの量です。 別の見方をすれば、そのプロセスがなくなったときにシステムで利用可能になるRAMです(おそらくすぐにキャッシュや他の用途に吸収されるでしょう)。

これがSDKのAPIのほぼ全てです。 しかし、開発者としてあなたのデバイスでできることはもっとあります。

使用方法 adb を使えば、実行中のシステムのメモリ使用量について多くの情報を得ることができます。 一般的なものは、コマンド adb shell dumpsys meminfo これは、各Javaプロセスのメモリ使用量について、上記の情報と他の様々なものを含む多くの情報を吐き出すものです。 また、1つのプロセスの名前かpidを付けて、例えば次のように見ることもできます。 adb shell dumpsys meminfo system システムプロセスを教えてください。

** pid 890 [system]のMEMINFO **。
                    ネイティブ ダルビック その他 合計
            サイズ: 10940 7047 N/A 17987
       が割り当てられています。    8943 5516 無し 14459
            フリー      336 1531 未満 1867
           (Pss): 4585 9282 11916 25783
  (共有ダーティ): 2184 3596 916 6696
    (プライベートダーティ): 4504 5956 7456 17916

 対象物
           ビュー      149 ビュールート: 4
     AppContexts。      13 アクティビティ        0
          アセット        4 アセットマネージャー: 4
   ローカルバインダー      141 プロキシバインダー      158
死亡者数       49
 OpenSSL ソケット        0

 SQL
            ヒープ: 205 dbFiles:        0
       numPagers: 0 inactivePageKB: 0
    アクティブページKB: 0


上段がメインで、ここで size は、特定のヒープのアドレス空間における総サイズです。 allocated は、そのヒープが持っていると考えている実際のアロケーションのkbです。 free は、ヒープが追加で割り当てることができる残りのKBで psspriv dirty は、それぞれのヒープに関連するページについて、前に説明したのと同じです。

全プロセスのメモリ使用量を見るだけなら、コマンド adb shell procrank . 同じシステムでこれを出力すると、次のようになります。

  PID Vss Rss Pss Uss cmdline
  890 84456K 48668K 25850K 21284K system_server
 1231 50748K 39088K 17587K 13792K com.android.launcher2
  947 34488K 28528K 10834K 9308K com.android.wallpaper
  987 26964K 26956K 8751K 7308K com.google.process.gapps
  954 24300K 24296K 6249K 4824K com.android.phone
  948 23020K 23016K 5864K 4748K com.android.inputmethod.latin
  888 25728K 25724K 5774K 3668K zygote
  977 24100K 24096K 5667K 4340K android.process.acore
...
   59 336K 332K 99K 92K /system/bin/installd
   60 396K 392K 93K 84K /system/bin/keystore
   51 280K 276K 74K 68K /system/bin/servicemanager
   54 256K 252K 69K 64K /system/bin/debuggerd

ここで VssRss 列は基本的にノイズです (これらはプロセスのアドレス空間と RAM 使用量です。プロセス全体の RAM 使用量を合計すると、とんでもなく大きな数字になります)。

Pss は以前から見てきたとおりで UssPriv Dirty .

ここで興味深いことがあります。 PssUss で見たものとは若干(いや、それ以上)異なっています。 meminfo . なぜでしょうか? procrankはデータを収集するのに違うカーネル・メカニズムを使います。 meminfo となり、微妙に異なる結果が得られます。 それはなぜか? 正直なところ、私にはわかりません。 私は procrank しかし、これはあくまで「塩の粒のような、しばしば非常に大きな粒のような記憶情報を入手すること」である。

最後にコマンドを紹介します。 adb shell cat /proc/meminfo これは、システム全体のメモリ使用量の概要を示すものです。 ここにはたくさんのデータがありますが、議論に値するのは最初の数個だけです (そして残りの数値はほとんど理解されておらず、私がその数人に質問すると、しばしば矛盾した説明になってしまいます)。

メモリ総量:395144kB
メモリフリー:184936キロバイト
バッファ             880キロバイト
キャッシュ:84104kB
SwapCached:            0 kB

MemTotal は、カーネルとユーザースペースが利用できるメモリの合計量です(RAMの一部は無線やDMAバッファなどに必要なため、デバイスの実際の物理RAMより少ないことがよくあります)。

MemFree は、全く使用されていないRAMの量です。 Androidシステムでは、プロセスを実行し続けるために使用可能なメモリを使用しようとするため、通常、これは数MBにしかなりません。

Cached は、ファイルシステムのキャッシュなどに使用されるRAMです。 Android のメモリ不足解消ツールは、キャッシュされた RAM が消費されすぎてページングが発生する前にバックグラウンドプロセスを終了させるよう、特定のシステム向けに調整されています。