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_AVERAGE; 20 import static com.android.internal.app.procstats.ProcessStats.PSS_COUNT; 21 import static com.android.internal.app.procstats.ProcessStats.PSS_MAXIMUM; 22 import static com.android.internal.app.procstats.ProcessStats.PSS_MINIMUM; 23 import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_AVERAGE; 24 import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MAXIMUM; 25 import static com.android.internal.app.procstats.ProcessStats.PSS_RSS_MINIMUM; 26 import static com.android.internal.app.procstats.ProcessStats.PSS_SAMPLE_COUNT; 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_USS_MINIMUM; 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 } 137 138 stats[statsIndex + PSS_RSS_AVERAGE] = (long)(((stats[statsIndex + PSS_RSS_AVERAGE] 139 * (double)count) + (avgRss * (double)inCount)) / (count + inCount)); 140 141 if (stats[statsIndex + PSS_RSS_MAXIMUM] < maxRss) { 142 stats[statsIndex + PSS_RSS_MAXIMUM] = maxRss; 143 } 144 } 145 } 146 writeStatsToProtoForKey(ProtoOutputStream proto, int key)147 public void writeStatsToProtoForKey(ProtoOutputStream proto, int key) { 148 final long[] stats = getArrayForKey(key); 149 final int statsIndex = SparseMappingTable.getIndexFromKey(key); 150 writeStatsToProto(proto, stats, statsIndex); 151 } 152 writeStatsToProto(ProtoOutputStream proto, final long[] stats, final int statsIndex)153 public static void writeStatsToProto(ProtoOutputStream proto, final long[] stats, 154 final int statsIndex) { 155 proto.write(ProcessStatsStateProto.SAMPLE_SIZE, stats[statsIndex + PSS_SAMPLE_COUNT]); 156 ProtoUtils.toAggStatsProto(proto, ProcessStatsStateProto.PSS, 157 stats[statsIndex + PSS_MINIMUM], 158 stats[statsIndex + PSS_AVERAGE], 159 stats[statsIndex + PSS_MAXIMUM]); 160 ProtoUtils.toAggStatsProto(proto, ProcessStatsStateProto.USS, 161 stats[statsIndex + PSS_USS_MINIMUM], 162 stats[statsIndex + PSS_USS_AVERAGE], 163 stats[statsIndex + PSS_USS_MAXIMUM]); 164 ProtoUtils.toAggStatsProto(proto, ProcessStatsStateProto.RSS, 165 stats[statsIndex + PSS_RSS_MINIMUM], 166 stats[statsIndex + PSS_RSS_AVERAGE], 167 stats[statsIndex + PSS_RSS_MAXIMUM]); 168 } 169 getRssMeanAndMax(int key)170 long[] getRssMeanAndMax(int key) { 171 final long[] stats = getArrayForKey(key); 172 final int statsIndex = SparseMappingTable.getIndexFromKey(key); 173 return new long[]{stats[statsIndex + PSS_RSS_AVERAGE], stats[statsIndex + PSS_RSS_MAXIMUM]}; 174 } 175 } 176