blob: e71bc55596d9fb5406a62c5ef86ad1b1a5e25501 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.internal.app.procstats;
import android.util.DebugUtils;
import static com.android.internal.app.procstats.ProcessStats.STATE_COUNT;
import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_SAMPLE_COUNT;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_CACHED_MINIMUM;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_CACHED_AVERAGE;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_CACHED_MAXIMUM;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_FREE_MINIMUM;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_FREE_AVERAGE;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_FREE_MAXIMUM;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_ZRAM_MINIMUM;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_ZRAM_AVERAGE;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_ZRAM_MAXIMUM;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_KERNEL_MINIMUM;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_KERNEL_AVERAGE;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_KERNEL_MAXIMUM;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_NATIVE_MINIMUM;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_NATIVE_AVERAGE;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_NATIVE_MAXIMUM;
import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_COUNT;
import java.io.PrintWriter;
/**
* Class to accumulate system mem usage data.
*/
public class SysMemUsageTable extends SparseMappingTable.Table {
/**
* Construct the SysMemUsageTable with 'tableData' as backing store
* for the longs data.
*/
public SysMemUsageTable(SparseMappingTable tableData) {
super(tableData);
}
/**
* Merge the stats given into our own values.
*
* @param that SysMemUsageTable to copy from.
*/
public void mergeStats(SysMemUsageTable that) {
final int N = that.getKeyCount();
for (int i=0; i<N; i++) {
final int key = that.getKeyAt(i);
final int state = SparseMappingTable.getIdFromKey(key);
final long[] addData = that.getArrayForKey(key);
final int addOff = SparseMappingTable.getIndexFromKey(key);
mergeStats(state, addData, addOff);
}
}
/**
* Merge the stats given into our own values.
*
* @param state The state
* @param addData The data array to copy
* @param addOff The index in addOff to start copying from
*/
public void mergeStats(int state, long[] addData, int addOff) {
final int key = getOrAddKey((byte)state, SYS_MEM_USAGE_COUNT);
final long[] dstData = getArrayForKey(key);
final int dstOff = SparseMappingTable.getIndexFromKey(key);
SysMemUsageTable.mergeSysMemUsage(dstData, dstOff, addData, addOff);
}
/**
* Return a long[] containing the merge of all of the usage in this table.
*/
public long[] getTotalMemUsage() {
long[] total = new long[SYS_MEM_USAGE_COUNT];
final int N = getKeyCount();
for (int i=0; i<N; i++) {
final int key = getKeyAt(i);
final long[] addData = getArrayForKey(key);
final int addOff = SparseMappingTable.getIndexFromKey(key);
SysMemUsageTable.mergeSysMemUsage(total, 0, addData, addOff);
}
return total;
}
/**
* Merge the stats from one raw long[] into another.
*
* @param dstData The destination array
* @param dstOff The index in the destination array to start from
* @param addData The source array
* @param addOff The index in the source array to start from
*/
public static void mergeSysMemUsage(long[] dstData, int dstOff,
long[] addData, int addOff) {
final long dstCount = dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT];
final long addCount = addData[addOff+SYS_MEM_USAGE_SAMPLE_COUNT];
if (dstCount == 0) {
dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT] = addCount;
for (int i=SYS_MEM_USAGE_CACHED_MINIMUM; i<SYS_MEM_USAGE_COUNT; i++) {
dstData[dstOff+i] = addData[addOff+i];
}
} else if (addCount > 0) {
dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT] = dstCount + addCount;
for (int i=SYS_MEM_USAGE_CACHED_MINIMUM; i<SYS_MEM_USAGE_COUNT; i+=3) {
if (dstData[dstOff+i] > addData[addOff+i]) {
dstData[dstOff+i] = addData[addOff+i];
}
dstData[dstOff+i+1] = (long)(
((dstData[dstOff+i+1]*(double)dstCount)
+ (addData[addOff+i+1]*(double)addCount))
/ (dstCount+addCount) );
if (dstData[dstOff+i+2] < addData[addOff+i+2]) {
dstData[dstOff+i+2] = addData[addOff+i+2];
}
}
}
}
public void dump(PrintWriter pw, String prefix, int[] screenStates, int[] memStates) {
int printedScreen = -1;
for (int is=0; is<screenStates.length; is++) {
int printedMem = -1;
for (int im=0; im<memStates.length; im++) {
final int iscreen = screenStates[is];
final int imem = memStates[im];
final int bucket = ((iscreen + imem) * STATE_COUNT);
long count = getValueForId((byte)bucket, SYS_MEM_USAGE_SAMPLE_COUNT);
if (count > 0) {
pw.print(prefix);
if (screenStates.length > 1) {
DumpUtils.printScreenLabel(pw, printedScreen != iscreen
? iscreen : STATE_NOTHING);
printedScreen = iscreen;
}
if (memStates.length > 1) {
DumpUtils.printMemLabel(pw,
printedMem != imem ? imem : STATE_NOTHING, '\0');
printedMem = imem;
}
pw.print(": ");
pw.print(count);
pw.println(" samples:");
dumpCategory(pw, prefix, " Cached", bucket, SYS_MEM_USAGE_CACHED_MINIMUM);
dumpCategory(pw, prefix, " Free", bucket, SYS_MEM_USAGE_FREE_MINIMUM);
dumpCategory(pw, prefix, " ZRam", bucket, SYS_MEM_USAGE_ZRAM_MINIMUM);
dumpCategory(pw, prefix, " Kernel", bucket, SYS_MEM_USAGE_KERNEL_MINIMUM);
dumpCategory(pw, prefix, " Native", bucket, SYS_MEM_USAGE_NATIVE_MINIMUM);
}
}
}
}
private void dumpCategory(PrintWriter pw, String prefix, String label, int bucket, int index) {
pw.print(prefix); pw.print(label);
pw.print(": ");
DebugUtils.printSizeValue(pw, getValueForId((byte)bucket, index) * 1024);
pw.print(" min, ");
DebugUtils.printSizeValue(pw, getValueForId((byte)bucket, index + 1) * 1024);
pw.print(" avg, ");
DebugUtils.printSizeValue(pw, getValueForId((byte)bucket, index+2) * 1024);
pw.println(" max");
}
}