Android: プロセス毎のメモリ取得について

Androidアプリのプロセス毎のメモリ使用量を知りたくて調べていたのだけれど、よくわからないまま。まず方法がわかっていなかったので、検索して一通り調べた後、twitterで#androidevを付けて質問。すると、psコマンドで取得した戻り値をうまいこと処理したらどうか?と言われて、なるほどと。そう思ってpsコマンドを打ってみたところ、なんかすごい量のメモリを使ってるアプリばかりだと。自分が使っているProcessManagerというアプリで示されているメモリ使用量のおよそ3倍くらいをほとんどのアプリが使っていることになっていた。そんなにメモリないだろうに、どういうことだろう?と思って呟いていたら、瀬戸デ部な方々が反応してくれた。

あれこれやってみた後に、topコマンドから取得したRSSじゃないか?という話になったんだけれど、この値も結局3倍くらいあるようで怪しいと…。このまま結局わからずじまいでとりあえず他のことをやろうと思って別件に取り組んでしまった(実は探偵ナイトスクープ見たあとにやろうと思っていたのにすっかり忘れていた)。

そして、土曜日のAndroid勉強会@愛媛 3回目にて、再度チャレンジ。そのときにstachibanaさんに聞いたら、以下のページはどうですか?と教えてくれた。
http://stackoverflow.com/questions/2298208/how-to-discover-memory-usage-of-my-application-in-android

なるほど、まさにそのような内容である。
が、全編英語なので、とりあえず、はしょりながら読む。

AcitivityManager.getProcessMemoryInfoというメソッドがあるらしい!
そして構造は以下の通り。

/** 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;

ただ、これらがどういう値を示しているのかがいまいち良く分からない。
英語のほうでは、「共有メモリの量も入ってるから、合計するとおそらく物理メモリ量よりも多くなるだろう」と書かれているっぽい。

PrivateDIrtyというのが、他のプロセスとシェアしていない、1プロセスのみでの物理メモリ使用量なのではないか?と思う。(プロセスがなくなったらシステムがそのメモリを利用可能になるとかかれていたので)

ほぼリンク先に書かれているソースになってしまうけれど書かせてもらう。

ActivityManager am = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
PackageManager pm = getPackageManager();
// 現在稼働中のプロセスをLISTで取得
List<RunningAppProcessInfo> rapis= am.getRunningAppProcesses();

// プロセスIDとプロセス名のマップを作成
Map<Integer, String> pidMap = new TreeMap<Integer, String>();
for(RunningAppProcessInfo rapi : rapis) {
	pidMap.put(rapi.pid, rapi.processName);
}
			
Collection<Integer> keys = pidMap.keySet();
for (int key : keys) {
	int pids[] = new int[1];
	pids[0] = key;
	// プロセスのメモリ情報を取得
	android.os.Debug.MemoryInfo[] memoryInfos = am.getProcessMemoryInfo(pids);
	for (android.os.Debug.MemoryInfo memoryInfo : memoryInfos) {
		ApplicationInfo ai;
		ai = pm.getApplicationInfo(pidMap.get(pids[0]), 0);
		// メモリ情報を取得するためのサンプル
		// ただ、どの値が何を示しているのかが、理解できていない…。
		//
		Log.d(TAG, String.format("** MEMINFO in pid %d [%s] **\n", pids[0], pidMap.get(pids[0])));
		Log.d(TAG, " AppName: " + pm.getApplicationLabel(ai));
		Log.d(TAG, " memoryInfo.getTotalPrivateDirty(): " + memoryInfo.getTotalPrivateDirty());
		Log.d(TAG, " memoryInfo.getTotalPss(): " + memoryInfo.getTotalPss());
		Log.d(TAG, " memoryInfo.getTotalSharedDirty(): " + memoryInfo.getTotalSharedDirty());
	}
}

これでプロセス単位でメモリの情報は取れる!のだけれど、取得した本人が、よくわかっていないので、どれを使えばいいのやら…。英語に堪能な方に教えてもらいたい。また、英語の重要性を知る事になる。いつもいつも思うのだけれどね…。


カテゴリー Android | タグ | パーマリンク

コメント・トラックバック一覧

  1. kazunobu says:

    自分も「Android: プロセス毎のメモリ取得について」に掲載して頂いた方法で、プロセス毎の使用メモリを取得したいと考えています。
    エミュレータでは動作確認できたのですが、実機で動作させた場合、Android Systemしか取得できません。
    マニフェストのandroid.permissionなど、別途設定が必要でしょうか??

  2. ソースを見直してみましたが、
    マニフェストには特に指定はしてないですねぇ…。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です