1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.app.procstats; 18 19 import android.util.DebugUtils; 20 21 import static com.android.internal.app.procstats.ProcessStats.STATE_COUNT; 22 import static com.android.internal.app.procstats.ProcessStats.STATE_NOTHING; 23 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_SAMPLE_COUNT; 24 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_CACHED_MINIMUM; 25 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_CACHED_AVERAGE; 26 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_CACHED_MAXIMUM; 27 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_FREE_MINIMUM; 28 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_FREE_AVERAGE; 29 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_FREE_MAXIMUM; 30 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_ZRAM_MINIMUM; 31 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_ZRAM_AVERAGE; 32 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_ZRAM_MAXIMUM; 33 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_KERNEL_MINIMUM; 34 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_KERNEL_AVERAGE; 35 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_KERNEL_MAXIMUM; 36 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_NATIVE_MINIMUM; 37 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_NATIVE_AVERAGE; 38 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_NATIVE_MAXIMUM; 39 import static com.android.internal.app.procstats.ProcessStats.SYS_MEM_USAGE_COUNT; 40 41 import java.io.PrintWriter; 42 43 44 /** 45 * Class to accumulate system mem usage data. 46 */ 47 public class SysMemUsageTable extends SparseMappingTable.Table { 48 /** 49 * Construct the SysMemUsageTable with 'tableData' as backing store 50 * for the longs data. 51 */ SysMemUsageTable(SparseMappingTable tableData)52 public SysMemUsageTable(SparseMappingTable tableData) { 53 super(tableData); 54 } 55 56 /** 57 * Merge the stats given into our own values. 58 * 59 * @param that SysMemUsageTable to copy from. 60 */ mergeStats(SysMemUsageTable that)61 public void mergeStats(SysMemUsageTable that) { 62 final int N = that.getKeyCount(); 63 for (int i=0; i<N; i++) { 64 final int key = that.getKeyAt(i); 65 66 final int state = SparseMappingTable.getIdFromKey(key); 67 final long[] addData = that.getArrayForKey(key); 68 final int addOff = SparseMappingTable.getIndexFromKey(key); 69 70 mergeStats(state, addData, addOff); 71 } 72 } 73 74 /** 75 * Merge the stats given into our own values. 76 * 77 * @param state The state 78 * @param addData The data array to copy 79 * @param addOff The index in addOff to start copying from 80 */ mergeStats(int state, long[] addData, int addOff)81 public void mergeStats(int state, long[] addData, int addOff) { 82 final int key = getOrAddKey((byte)state, SYS_MEM_USAGE_COUNT); 83 84 final long[] dstData = getArrayForKey(key); 85 final int dstOff = SparseMappingTable.getIndexFromKey(key); 86 87 SysMemUsageTable.mergeSysMemUsage(dstData, dstOff, addData, addOff); 88 } 89 90 /** 91 * Return a long[] containing the merge of all of the usage in this table. 92 */ getTotalMemUsage()93 public long[] getTotalMemUsage() { 94 long[] total = new long[SYS_MEM_USAGE_COUNT]; 95 final int N = getKeyCount(); 96 for (int i=0; i<N; i++) { 97 final int key = getKeyAt(i); 98 99 final long[] addData = getArrayForKey(key); 100 final int addOff = SparseMappingTable.getIndexFromKey(key); 101 102 SysMemUsageTable.mergeSysMemUsage(total, 0, addData, addOff); 103 } 104 return total; 105 } 106 107 /** 108 * Merge the stats from one raw long[] into another. 109 * 110 * @param dstData The destination array 111 * @param dstOff The index in the destination array to start from 112 * @param addData The source array 113 * @param addOff The index in the source array to start from 114 */ mergeSysMemUsage(long[] dstData, int dstOff, long[] addData, int addOff)115 public static void mergeSysMemUsage(long[] dstData, int dstOff, 116 long[] addData, int addOff) { 117 final long dstCount = dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT]; 118 final long addCount = addData[addOff+SYS_MEM_USAGE_SAMPLE_COUNT]; 119 if (dstCount == 0) { 120 dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT] = addCount; 121 for (int i=SYS_MEM_USAGE_CACHED_MINIMUM; i<SYS_MEM_USAGE_COUNT; i++) { 122 dstData[dstOff+i] = addData[addOff+i]; 123 } 124 } else if (addCount > 0) { 125 dstData[dstOff+SYS_MEM_USAGE_SAMPLE_COUNT] = dstCount + addCount; 126 for (int i=SYS_MEM_USAGE_CACHED_MINIMUM; i<SYS_MEM_USAGE_COUNT; i+=3) { 127 if (dstData[dstOff+i] > addData[addOff+i]) { 128 dstData[dstOff+i] = addData[addOff+i]; 129 } 130 dstData[dstOff+i+1] = (long)( 131 ((dstData[dstOff+i+1]*(double)dstCount) 132 + (addData[addOff+i+1]*(double)addCount)) 133 / (dstCount+addCount) ); 134 if (dstData[dstOff+i+2] < addData[addOff+i+2]) { 135 dstData[dstOff+i+2] = addData[addOff+i+2]; 136 } 137 } 138 } 139 } 140 141 dump(PrintWriter pw, String prefix, int[] screenStates, int[] memStates)142 public void dump(PrintWriter pw, String prefix, int[] screenStates, int[] memStates) { 143 int printedScreen = -1; 144 for (int is=0; is<screenStates.length; is++) { 145 int printedMem = -1; 146 for (int im=0; im<memStates.length; im++) { 147 final int iscreen = screenStates[is]; 148 final int imem = memStates[im]; 149 final int bucket = ((iscreen + imem) * STATE_COUNT); 150 long count = getValueForId((byte)bucket, SYS_MEM_USAGE_SAMPLE_COUNT); 151 if (count > 0) { 152 pw.print(prefix); 153 if (screenStates.length > 1) { 154 DumpUtils.printScreenLabel(pw, printedScreen != iscreen 155 ? iscreen : STATE_NOTHING); 156 printedScreen = iscreen; 157 } 158 if (memStates.length > 1) { 159 DumpUtils.printMemLabel(pw, 160 printedMem != imem ? imem : STATE_NOTHING, '\0'); 161 printedMem = imem; 162 } 163 pw.print(": "); 164 pw.print(count); 165 pw.println(" samples:"); 166 dumpCategory(pw, prefix, " Cached", bucket, SYS_MEM_USAGE_CACHED_MINIMUM); 167 dumpCategory(pw, prefix, " Free", bucket, SYS_MEM_USAGE_FREE_MINIMUM); 168 dumpCategory(pw, prefix, " ZRam", bucket, SYS_MEM_USAGE_ZRAM_MINIMUM); 169 dumpCategory(pw, prefix, " Kernel", bucket, SYS_MEM_USAGE_KERNEL_MINIMUM); 170 dumpCategory(pw, prefix, " Native", bucket, SYS_MEM_USAGE_NATIVE_MINIMUM); 171 } 172 } 173 } 174 } 175 dumpCategory(PrintWriter pw, String prefix, String label, int bucket, int index)176 private void dumpCategory(PrintWriter pw, String prefix, String label, int bucket, int index) { 177 pw.print(prefix); pw.print(label); 178 pw.print(": "); 179 DebugUtils.printSizeValue(pw, getValueForId((byte)bucket, index) * 1024); 180 pw.print(" min, "); 181 DebugUtils.printSizeValue(pw, getValueForId((byte)bucket, index + 1) * 1024); 182 pw.print(" avg, "); 183 DebugUtils.printSizeValue(pw, getValueForId((byte)bucket, index+2) * 1024); 184 pw.println(" max"); 185 } 186 187 } 188 189 190