Merge "Implement issue #11050739: Show swapped out RAM" into klp-dev

This commit is contained in:
Dianne Hackborn
2013-10-03 17:45:42 +00:00
committed by Android (Google) Code Review
3 changed files with 103 additions and 44 deletions

View File

@@ -533,8 +533,10 @@ public final class ActivityThread {
private native void dumpGraphicsInfo(FileDescriptor fd);
private class ApplicationThread extends ApplicationThreadNative {
private static final String HEAP_FULL_COLUMN = "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s";
private static final String HEAP_COLUMN = "%13s %8s %8s %8s %8s %8s %8s %8s";
private static final String HEAP_FULL_COLUMN
= "%13s %8s %8s %8s %8s %8s %8s %8s %8s %8s %8s";
private static final String HEAP_COLUMN
= "%13s %8s %8s %8s %8s %8s %8s %8s";
private static final String ONE_COUNT_COLUMN = "%21s %8d";
private static final String TWO_COUNT_COLUMNS = "%21s %8d %21s %8d";
private static final String DB_INFO_FORMAT = " %8s %8s %14s %14s %s";
@@ -1039,34 +1041,36 @@ public final class ActivityThread {
// otherwise, show human-readable format
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "", "Pss", "Pss", "Shared", "Private",
"Shared", "Private", "Heap", "Heap", "Heap");
"Shared", "Private", "Swapped", "Heap", "Heap", "Heap");
printRow(pw, HEAP_FULL_COLUMN, "", "Total", "Clean", "Dirty", "Dirty",
"Clean", "Clean", "Size", "Alloc", "Free");
"Clean", "Clean", "Dirty", "Size", "Alloc", "Free");
printRow(pw, HEAP_FULL_COLUMN, "", "------", "------", "------", "------",
"------", "------", "------", "------", "------");
"------", "------", "------", "------", "------", "------");
printRow(pw, HEAP_FULL_COLUMN, "Native Heap", memInfo.nativePss,
memInfo.nativeSwappablePss, memInfo.nativeSharedDirty,
memInfo.nativePrivateDirty, memInfo.nativeSharedClean,
memInfo.nativePrivateClean, nativeMax, nativeAllocated, nativeFree);
memInfo.nativePrivateClean, memInfo.nativeSwappedOut,
nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_FULL_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
memInfo.dalvikSwappablePss, memInfo.dalvikSharedDirty,
memInfo.dalvikPrivateDirty, memInfo.dalvikSharedClean,
memInfo.dalvikPrivateClean, dalvikMax, dalvikAllocated, dalvikFree);
memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut,
dalvikMax, dalvikAllocated, dalvikFree);
} else {
printRow(pw, HEAP_COLUMN, "", "Pss", "Pss", "Private",
"Private", "Heap", "Heap", "Heap");
printRow(pw, HEAP_COLUMN, "", "Total", "Clean", "Dirty",
"Clean", "Size", "Alloc", "Free");
printRow(pw, HEAP_COLUMN, "", "Pss", "Private",
"Private", "Swapped", "Heap", "Heap", "Heap");
printRow(pw, HEAP_COLUMN, "", "Total", "Dirty",
"Clean", "Dirty", "Size", "Alloc", "Free");
printRow(pw, HEAP_COLUMN, "", "------", "------", "------",
"------", "------", "------", "------");
"------", "------", "------", "------", "------");
printRow(pw, HEAP_COLUMN, "Native Heap", memInfo.nativePss,
memInfo.nativeSwappablePss,
memInfo.nativePrivateDirty,
memInfo.nativePrivateClean, nativeMax, nativeAllocated, nativeFree);
memInfo.nativePrivateClean, memInfo.nativeSwappedOut,
nativeMax, nativeAllocated, nativeFree);
printRow(pw, HEAP_COLUMN, "Dalvik Heap", memInfo.dalvikPss,
memInfo.dalvikSwappablePss,
memInfo.dalvikPrivateDirty,
memInfo.dalvikPrivateClean, dalvikMax, dalvikAllocated, dalvikFree);
memInfo.dalvikPrivateClean, memInfo.dalvikSwappedOut,
dalvikMax, dalvikAllocated, dalvikFree);
}
int otherPss = memInfo.otherPss;
@@ -1075,6 +1079,7 @@ public final class ActivityThread {
int otherPrivateDirty = memInfo.otherPrivateDirty;
int otherSharedClean = memInfo.otherSharedClean;
int otherPrivateClean = memInfo.otherPrivateClean;
int otherSwappedOut = memInfo.otherSwappedOut;
for (int i=0; i<Debug.MemoryInfo.NUM_OTHER_STATS; i++) {
final int myPss = memInfo.getOtherPss(i);
@@ -1083,16 +1088,17 @@ public final class ActivityThread {
final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
final int mySharedClean = memInfo.getOtherSharedClean(i);
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
|| mySharedClean != 0 || myPrivateClean != 0) {
|| mySharedClean != 0 || myPrivateClean != 0 || mySwappedOut != 0) {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
mySharedClean, myPrivateClean, "", "", "");
mySharedClean, myPrivateClean, mySwappedOut, "", "", "");
} else {
printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, myPrivateDirty,
myPrivateClean, "", "", "");
myPss, myPrivateDirty,
myPrivateClean, mySwappedOut, "", "", "");
}
otherPss -= myPss;
otherSwappablePss -= mySwappablePss;
@@ -1100,27 +1106,28 @@ public final class ActivityThread {
otherPrivateDirty -= myPrivateDirty;
otherSharedClean -= mySharedClean;
otherPrivateClean -= myPrivateClean;
otherSwappedOut -= mySwappedOut;
}
}
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, "Unknown", otherPss, otherSwappablePss,
otherSharedDirty, otherPrivateDirty, otherSharedClean, otherPrivateClean,
"", "", "");
otherSwappedOut, "", "", "");
printRow(pw, HEAP_FULL_COLUMN, "TOTAL", memInfo.getTotalPss(),
memInfo.getTotalSwappablePss(),
memInfo.getTotalSharedDirty(), memInfo.getTotalPrivateDirty(),
memInfo.getTotalSharedClean(), memInfo.getTotalPrivateClean(),
nativeMax+dalvikMax,
memInfo.getTotalSwappedOut(), nativeMax+dalvikMax,
nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
} else {
printRow(pw, HEAP_COLUMN, "Unknown", otherPss, otherSwappablePss,
otherPrivateDirty, otherPrivateClean,
printRow(pw, HEAP_COLUMN, "Unknown", otherPss,
otherPrivateDirty, otherPrivateClean, otherSwappedOut,
"", "", "");
printRow(pw, HEAP_COLUMN, "TOTAL", memInfo.getTotalPss(),
memInfo.getTotalSwappablePss(),
memInfo.getTotalPrivateDirty(),
memInfo.getTotalPrivateClean(),
memInfo.getTotalSwappedOut(),
nativeMax+dalvikMax,
nativeAllocated+dalvikAllocated, nativeFree+dalvikFree);
}
@@ -1137,16 +1144,17 @@ public final class ActivityThread {
final int myPrivateDirty = memInfo.getOtherPrivateDirty(i);
final int mySharedClean = memInfo.getOtherSharedClean(i);
final int myPrivateClean = memInfo.getOtherPrivateClean(i);
final int mySwappedOut = memInfo.getOtherSwappedOut(i);
if (myPss != 0 || mySharedDirty != 0 || myPrivateDirty != 0
|| mySharedClean != 0 || myPrivateClean != 0) {
if (dumpFullInfo) {
printRow(pw, HEAP_FULL_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, mySharedDirty, myPrivateDirty,
mySharedClean, myPrivateClean, "", "", "");
mySharedClean, myPrivateClean, mySwappedOut, "", "", "");
} else {
printRow(pw, HEAP_COLUMN, Debug.MemoryInfo.getOtherLabel(i),
myPss, mySwappablePss, myPrivateDirty,
myPrivateClean, "", "", "");
myPss, myPrivateDirty,
myPrivateClean, mySwappedOut, "", "", "");
}
}
}

View File

@@ -124,6 +124,9 @@ public final class Debug
/** The shared clean pages used by dalvik heap. */
/** @hide We may want to expose this, eventually. */
public int dalvikSharedClean;
/** The dirty dalvik pages that have been swapped out. */
/** @hide We may want to expose this, eventually. */
public int dalvikSwappedOut;
/** The proportional set size for the native heap. */
public int nativePss;
@@ -140,6 +143,9 @@ public final class Debug
/** The shared clean pages used by the native heap. */
/** @hide We may want to expose this, eventually. */
public int nativeSharedClean;
/** The dirty native pages that have been swapped out. */
/** @hide We may want to expose this, eventually. */
public int nativeSwappedOut;
/** The proportional set size for everything else. */
public int otherPss;
@@ -156,6 +162,9 @@ public final class Debug
/** The shared clean pages used by everything else. */
/** @hide We may want to expose this, eventually. */
public int otherSharedClean;
/** The dirty pages used by anyting else that have been swapped out. */
/** @hide We may want to expose this, eventually. */
public int otherSwappedOut;
/** @hide */
public static final int NUM_OTHER_STATS = 16;
@@ -164,7 +173,7 @@ public final class Debug
public static final int NUM_DVK_STATS = 5;
/** @hide */
public static final int NUM_CATEGORIES = 6;
public static final int NUM_CATEGORIES = 7;
/** @hide */
public static final int offsetPss = 0;
@@ -178,7 +187,8 @@ public final class Debug
public static final int offsetPrivateClean = 4;
/** @hide */
public static final int offsetSharedClean = 5;
/** @hide */
public static final int offsetSwappedOut = 6;
private int[] otherStats = new int[(NUM_OTHER_STATS+NUM_DVK_STATS)*NUM_CATEGORIES];
@@ -236,6 +246,14 @@ public final class Debug
return dalvikSharedClean + nativeSharedClean + otherSharedClean;
}
/**
* Return total swapped out memory in kB.
* @hide
*/
public int getTotalSwappedOut() {
return dalvikSwappedOut + nativeSwappedOut + otherSwappedOut;
}
/** @hide */
public int getOtherPss(int which) {
return otherStats[which*NUM_CATEGORIES + offsetPss];
@@ -263,12 +281,16 @@ public final class Debug
return otherStats[which*NUM_CATEGORIES + offsetPrivateClean];
}
/** @hide */
public int getOtherSharedClean(int which) {
return otherStats[which*NUM_CATEGORIES + offsetSharedClean];
}
/** @hide */
public int getOtherSwappedOut(int which) {
return otherStats[which*NUM_CATEGORIES + offsetSwappedOut];
}
/** @hide */
public static String getOtherLabel(int which) {
switch (which) {
@@ -287,7 +309,7 @@ public final class Debug
case 12: return "Other mmap";
case 13: return "Graphics";
case 14: return "GL";
case 15: return "Other memtrack";
case 15: return "Memtrack";
case 16: return ".Heap";
case 17: return ".LOS";
case 18: return ".LinearAlloc";
@@ -308,18 +330,21 @@ public final class Debug
dest.writeInt(dalvikSharedDirty);
dest.writeInt(dalvikPrivateClean);
dest.writeInt(dalvikSharedClean);
dest.writeInt(dalvikSwappedOut);
dest.writeInt(nativePss);
dest.writeInt(nativeSwappablePss);
dest.writeInt(nativePrivateDirty);
dest.writeInt(nativeSharedDirty);
dest.writeInt(nativePrivateClean);
dest.writeInt(nativeSharedClean);
dest.writeInt(nativeSwappedOut);
dest.writeInt(otherPss);
dest.writeInt(otherSwappablePss);
dest.writeInt(otherPrivateDirty);
dest.writeInt(otherSharedDirty);
dest.writeInt(otherPrivateClean);
dest.writeInt(otherSharedClean);
dest.writeInt(otherSwappedOut);
dest.writeIntArray(otherStats);
}
@@ -330,18 +355,21 @@ public final class Debug
dalvikSharedDirty = source.readInt();
dalvikPrivateClean = source.readInt();
dalvikSharedClean = source.readInt();
dalvikSwappedOut = source.readInt();
nativePss = source.readInt();
nativeSwappablePss = source.readInt();
nativePrivateDirty = source.readInt();
nativeSharedDirty = source.readInt();
nativePrivateClean = source.readInt();
nativeSharedClean = source.readInt();
nativeSwappedOut = source.readInt();
otherPss = source.readInt();
otherSwappablePss = source.readInt();
otherPrivateDirty = source.readInt();
otherSharedDirty = source.readInt();
otherPrivateClean = source.readInt();
otherSharedClean = source.readInt();
otherSwappedOut = source.readInt();
otherStats = source.createIntArray();
}

View File

@@ -80,6 +80,7 @@ struct stat_fields {
jfieldID sharedDirty_field;
jfieldID privateClean_field;
jfieldID sharedClean_field;
jfieldID swappedOut_field;
};
struct stat_field_names {
@@ -89,14 +90,18 @@ struct stat_field_names {
const char* sharedDirty_name;
const char* privateClean_name;
const char* sharedClean_name;
const char* swappedOut_name;
};
static stat_fields stat_fields[_NUM_CORE_HEAP];
static stat_field_names stat_field_names[_NUM_CORE_HEAP] = {
{ "otherPss", "otherSwappablePss", "otherPrivateDirty", "otherSharedDirty", "otherPrivateClean", "otherSharedClean" },
{ "dalvikPss", "dalvikSwappablePss", "dalvikPrivateDirty", "dalvikSharedDirty", "dalvikPrivateClean", "dalvikSharedClean" },
{ "nativePss", "nativeSwappablePss", "nativePrivateDirty", "nativeSharedDirty", "nativePrivateClean", "nativeSharedClean" }
{ "otherPss", "otherSwappablePss", "otherPrivateDirty", "otherSharedDirty",
"otherPrivateClean", "otherSharedClean", "otherSwappedOut" },
{ "dalvikPss", "dalvikSwappablePss", "dalvikPrivateDirty", "dalvikSharedDirty",
"dalvikPrivateClean", "dalvikSharedClean", "dalvikSwappedOut" },
{ "nativePss", "nativeSwappablePss", "nativePrivateDirty", "nativeSharedDirty",
"nativePrivateClean", "nativeSharedClean", "nativeSwappedOut" }
};
jfieldID otherStats_field;
@@ -110,6 +115,7 @@ struct stats_t {
int sharedDirty;
int privateClean;
int sharedClean;
int swappedOut;
};
#define BINDER_STATS "/proc/binder/stats"
@@ -219,6 +225,7 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
float sharing_proportion = 0.0;
unsigned shared_clean = 0, shared_dirty = 0;
unsigned private_clean = 0, private_dirty = 0;
unsigned swapped_out = 0;
bool is_swappable = false;
unsigned referenced = 0;
unsigned temp;
@@ -333,28 +340,36 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
//ALOGI("native=%d dalvik=%d sqlite=%d: %s\n", isNativeHeap, isDalvikHeap,
// isSqliteHeap, line);
shared_clean = 0;
shared_dirty = 0;
private_clean = 0;
private_dirty = 0;
swapped_out = 0;
while (true) {
if (fgets(line, 1024, fp) == 0) {
done = true;
break;
}
if (sscanf(line, "Size: %d kB", &temp) == 1) {
if (line[0] == 'S' && sscanf(line, "Size: %d kB", &temp) == 1) {
size = temp;
} else if (sscanf(line, "Rss: %d kB", &temp) == 1) {
} else if (line[0] == 'R' && sscanf(line, "Rss: %d kB", &temp) == 1) {
resident = temp;
} else if (sscanf(line, "Pss: %d kB", &temp) == 1) {
} else if (line[0] == 'P' && sscanf(line, "Pss: %d kB", &temp) == 1) {
pss = temp;
} else if (sscanf(line, "Shared_Clean: %d kB", &temp) == 1) {
} else if (line[0] == 'S' && sscanf(line, "Shared_Clean: %d kB", &temp) == 1) {
shared_clean = temp;
} else if (sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) {
} else if (line[0] == 'S' && sscanf(line, "Shared_Dirty: %d kB", &temp) == 1) {
shared_dirty = temp;
} else if (sscanf(line, "Private_Clean: %d kB", &temp) == 1) {
} else if (line[0] == 'P' && sscanf(line, "Private_Clean: %d kB", &temp) == 1) {
private_clean = temp;
} else if (sscanf(line, "Private_Dirty: %d kB", &temp) == 1) {
} else if (line[0] == 'P' && sscanf(line, "Private_Dirty: %d kB", &temp) == 1) {
private_dirty = temp;
} else if (sscanf(line, "Referenced: %d kB", &temp) == 1) {
} else if (line[0] == 'R' && sscanf(line, "Referenced: %d kB", &temp) == 1) {
referenced = temp;
} else if (line[0] == 'S' && sscanf(line, "Swap: %d kB", &temp) == 1) {
swapped_out = temp;
} else if (strlen(line) > 30 && line[8] == '-' && line[17] == ' ') {
// looks like a new mapping
// example: "10000000-10001000 ---p 10000000 00:00 0"
@@ -366,7 +381,8 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
if (is_swappable && (pss > 0)) {
sharing_proportion = 0.0;
if ((shared_clean > 0) || (shared_dirty > 0)) {
sharing_proportion = (pss - private_clean - private_dirty)/(shared_clean+shared_dirty);
sharing_proportion = (pss - private_clean
- private_dirty)/(shared_clean+shared_dirty);
}
swappable_pss = (sharing_proportion*shared_clean) + private_clean;
} else
@@ -378,6 +394,7 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
stats[whichHeap].sharedDirty += shared_dirty;
stats[whichHeap].privateClean += private_clean;
stats[whichHeap].sharedClean += shared_clean;
stats[whichHeap].swappedOut += swapped_out;
if (whichHeap == HEAP_DALVIK || whichHeap == HEAP_DALVIK_OTHER) {
stats[subHeap].pss += pss;
stats[subHeap].swappablePss += swappable_pss;
@@ -385,6 +402,7 @@ static void read_mapinfo(FILE *fp, stats_t* stats)
stats[subHeap].sharedDirty += shared_dirty;
stats[subHeap].privateClean += private_clean;
stats[subHeap].sharedClean += shared_clean;
stats[subHeap].swappedOut += swapped_out;
}
}
}
@@ -428,6 +446,7 @@ static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
stats[HEAP_UNKNOWN].sharedDirty += stats[i].sharedDirty;
stats[HEAP_UNKNOWN].privateClean += stats[i].privateClean;
stats[HEAP_UNKNOWN].sharedClean += stats[i].sharedClean;
stats[HEAP_UNKNOWN].swappedOut += stats[i].swappedOut;
}
for (int i=0; i<_NUM_CORE_HEAP; i++) {
@@ -437,6 +456,7 @@ static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
env->SetIntField(object, stat_fields[i].sharedDirty_field, stats[i].sharedDirty);
env->SetIntField(object, stat_fields[i].privateClean_field, stats[i].privateClean);
env->SetIntField(object, stat_fields[i].sharedClean_field, stats[i].sharedClean);
env->SetIntField(object, stat_fields[i].swappedOut_field, stats[i].swappedOut);
}
@@ -455,6 +475,7 @@ static void android_os_Debug_getDirtyPagesPid(JNIEnv *env, jobject clazz,
otherArray[j++] = stats[i].sharedDirty;
otherArray[j++] = stats[i].privateClean;
otherArray[j++] = stats[i].sharedClean;
otherArray[j++] = stats[i].swappedOut;
}
env->ReleasePrimitiveArrayCritical(otherIntArray, otherArray, 0);
@@ -971,6 +992,8 @@ int register_android_os_Debug(JNIEnv *env)
env->GetFieldID(clazz, stat_field_names[i].privateClean_name, "I");
stat_fields[i].sharedClean_field =
env->GetFieldID(clazz, stat_field_names[i].sharedClean_name, "I");
stat_fields[i].swappedOut_field =
env->GetFieldID(clazz, stat_field_names[i].swappedOut_name, "I");
}
return jniRegisterNativeMethods(env, "android/os/Debug", gMethods, NELEM(gMethods));