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 static com.android.internal.app.procstats.ProcessStats.PSS_RSS_AVERAGE; 20 import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MAXIMUM; 21 import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MINIMUM; 22 import static com.android.internal.app.procstats.ProcessStats.PSS_SAMPLE_COUNT; 23 import static com.android.internal.app.procstats.ProcessStats.PSS_MINIMUM; 24 import static com.android.internal.app.procstats.ProcessStats.PSS_AVERAGE; 25 import static com.android.internal.app.procstats.ProcessStats.PSS_MAXIMUM; 26 import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MINIMUM; 27 import static com.android.internal.app.procstats.ProcessStats.PSS_USS_AVERAGE; 28 import static com.android.internal.app.procstats.ProcessStats.PSS_USS_MAXIMUM; 29 import static com.android.internal.app.procstats.ProcessStats.PSS_COUNT; 30 31 import android.service.procstats.ProcessStatsStateProto; 32 import android.util.proto.ProtoOutputStream; 33 import android.util.proto.ProtoUtils; 34 35 /** 36 * Class to accumulate PSS data. 37 */ 38 public class PssTable extends SparseMappingTable.Table { 39 /** 40 * Construct the PssTable with 'tableData' as backing store 41 * for the longs data. 42 */ PssTable(SparseMappingTable tableData)43 public PssTable(SparseMappingTable tableData) { 44 super(tableData); 45 } 46 47 /** 48 * Merge the the values from the other table into this one. 49 */ mergeStats(PssTable that)50 public void mergeStats(PssTable that) { 51 final int N = that.getKeyCount(); 52 for (int i=0; i<N; i++) { 53 final int thatKey = that.getKeyAt(i); 54 final int state = SparseMappingTable.getIdFromKey(thatKey); 55 56 final int key = getOrAddKey((byte)state, PSS_COUNT); 57 final long[] stats = getArrayForKey(key); 58 final int statsIndex = SparseMappingTable.getIndexFromKey(key); 59 60 final long[] thatStats = that.getArrayForKey(thatKey); 61 final int thatStatsIndex = SparseMappingTable.getIndexFromKey(thatKey); 62 63 mergeStats(stats, statsIndex, thatStats, thatStatsIndex); 64 } 65 } 66 67 /** 68 * Merge the supplied PSS data in. The new min pss will be the minimum of the existing 69 * one and the new one, the average will now incorporate the new average, etc. 70 */ mergeStats(int state, int inCount, long minPss, long avgPss, long maxPss, long minUss, long avgUss, long maxUss, long minRss, long avgRss, long maxRss)71 public void mergeStats(int state, int inCount, long minPss, long avgPss, long maxPss, 72 long minUss, long avgUss, long maxUss, long minRss, long avgRss, long maxRss) { 73 final int key = getOrAddKey((byte)state, PSS_COUNT); 74 final long[] stats = getArrayForKey(key); 75 final int statsIndex = SparseMappingTable.getIndexFromKey(key); 76 mergeStats(stats, statsIndex, inCount, minPss, avgPss, maxPss, minUss, avgUss, maxUss, 77 minRss, avgRss, maxRss); 78 } 79 mergeStats(final long[] stats, final int statsIndex, final long[] thatStats, int thatStatsIndex)80 public static void mergeStats(final long[] stats, final int statsIndex, 81 final long[] thatStats, int thatStatsIndex) { 82 mergeStats(stats, statsIndex, (int)thatStats[thatStatsIndex + PSS_SAMPLE_COUNT], 83 thatStats[thatStatsIndex + PSS_MINIMUM], 84 thatStats[thatStatsIndex + PSS_AVERAGE], 85 thatStats[thatStatsIndex + PSS_MAXIMUM], 86 thatStats[thatStatsIndex + PSS_USS_MINIMUM], 87 thatStats[thatStatsIndex + PSS_USS_AVERAGE], 88 thatStats[thatStatsIndex + PSS_USS_MAXIMUM], 89 thatStats[thatStatsIndex + PSS_RSS_MINIMUM], 90 thatStats[thatStatsIndex + PSS_RSS_AVERAGE], 91 thatStats[thatStatsIndex + PSS_RSS_MAXIMUM]); 92 } 93 mergeStats(final long[] stats, final int statsIndex, final int inCount, final long minPss, final long avgPss, final long maxPss, final long minUss, final long avgUss, final long maxUss, final long minRss, final long avgRss, final long maxRss)94 public static void mergeStats(final long[] stats, final int statsIndex, final int inCount, 95 final long minPss, final long avgPss, final long maxPss, 96 final long minUss, final long avgUss, final long maxUss, 97 final long minRss, final long avgRss, final long maxRss) { 98 final long count = stats[statsIndex + PSS_SAMPLE_COUNT]; 99 if (count == 0) { 100 stats[statsIndex + PSS_SAMPLE_COUNT] = inCount; 101 stats[statsIndex + PSS_MINIMUM] = minPss; 102 stats[statsIndex + PSS_AVERAGE] = avgPss; 103 stats[statsIndex + PSS_MAXIMUM] = maxPss; 104 stats[statsIndex + PSS_USS_MINIMUM] = minUss; 105 stats[statsIndex + PSS_USS_AVERAGE] = avgUss; 106 stats[statsIndex + PSS_USS_MAXIMUM] = maxUss; 107 stats[statsIndex + PSS_RSS_MINIMUM] = minRss; 108 stats[statsIndex + PSS_RSS_AVERAGE] = avgRss; 109 stats[statsIndex + PSS_RSS_MAXIMUM] = maxRss; 110 } else { 111 stats[statsIndex + PSS_SAMPLE_COUNT] = count + inCount; 112 113 if (stats[statsIndex + PSS_MINIMUM] > minPss) { 114 stats[statsIndex + PSS_MINIMUM] = minPss; 115 } 116 117 stats[statsIndex + PSS_AVERAGE] = (long)(((stats[statsIndex + PSS_AVERAGE] 118 * (double)count) + (avgPss * (double)inCount)) / (count + inCount)); 119 120 if (stats[statsIndex + PSS_MAXIMUM] < maxPss) { 121 stats[statsIndex + PSS_MAXIMUM] = maxPss; 122 } 123 124 if (stats[statsIndex + PSS_USS_MINIMUM] > minUss) { 125 stats[statsIndex + PSS_USS_MINIMUM] = minUss; 126 } 127 128 stats[statsIndex + PSS_USS_AVERAGE] = (long)(((stats[statsIndex + PSS_USS_AVERAGE] 129 * (double)count) + (avgUss * (double)inCount)) / (count + inCount)); 130 131 if (stats[statsIndex + PSS_USS_MAXIMUM] < maxUss) { 132 stats[statsIndex + PSS_USS_MAXIMUM] = maxUss; 133 } 134 135 if (stats[statsIndex + PSS_RSS_MINIMUM] > minRss) { 136 stats[statsIndex + PSS_RSS_MINIMUM] = minRss; 137 } 138 139 stats[statsIndex + PSS_RSS_AVERAGE] = (long)(((stats[statsIndex + PSS_RSS_AVERAGE] 140 * (double)count) + (avgRss * (double)inCount)) / (count + inCount)); 141 142 if (stats[statsIndex + PSS_RSS_MAXIMUM] < maxRss) { 143 stats[statsIndex + PSS_RSS_MAXIMUM] = maxRss; 144 } 145 } 146 } 147 writeStatsToProtoForKey(ProtoOutputStream proto, int key)148 public void writeStatsToProtoForKey(ProtoOutputStream proto, int key) { 149 final long[] stats = getArrayForKey(key); 150 final int statsIndex = SparseMappingTable.getIndexFromKey(key); 151 writeStatsToProto(proto, stats, statsIndex); 152 } 153 writeStatsToProto(ProtoOutputStream proto, final long[] stats, final int statsIndex)154 public static void writeStatsToProto(ProtoOutputStream proto, final long[] stats, 155 final int statsIndex) { 156 proto.write(ProcessStatsStateProto.SAMPLE_SIZE, stats[statsIndex + PSS_SAMPLE_COUNT]); 157 ProtoUtils.toAggStatsProto(proto, ProcessStatsStateProto.PSS, 158 stats[statsIndex + PSS_MINIMUM], 159 stats[statsIndex + PSS_AVERAGE], 160 stats[statsIndex + PSS_MAXIMUM]); 161 ProtoUtils.toAggStatsProto(proto, ProcessStatsStateProto.USS, 162 stats[statsIndex + PSS_USS_MINIMUM], 163 stats[statsIndex + PSS_USS_AVERAGE], 164 stats[statsIndex + PSS_USS_MAXIMUM]); 165 ProtoUtils.toAggStatsProto(proto, ProcessStatsStateProto.RSS, 166 stats[statsIndex + PSS_RSS_MINIMUM], 167 stats[statsIndex + PSS_RSS_AVERAGE], 168 stats[statsIndex + PSS_RSS_MAXIMUM]); 169 } 170 } 171