Home | History | Annotate | Download | only in procstats
      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      */
     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      */
     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      */
     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      */
     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      */
    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 
    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 
    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