1917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/* 2917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Copyright (C) 2007 The Android Open Source Project 3917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 4917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Licensed under the Apache License, Version 2.0 (the "License"); 5917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * you may not use this file except in compliance with the License. 6917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * You may obtain a copy of the License at 7917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 8917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * http://www.apache.org/licenses/LICENSE-2.0 9917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 10917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Unless required by applicable law or agreed to in writing, software 11917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * distributed under the License is distributed on an "AS IS" BASIS, 12917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * See the License for the specific language governing permissions and 14917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * limitations under the License. 15917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 16917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 17917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpackage com.android.dexgen.dex.file; 18917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 19917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport com.android.dexgen.util.AnnotatedOutput; 20917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 21917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.Collection; 22917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.HashMap; 23917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulimport java.util.TreeMap; 24917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 25917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul/** 26917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Statistics about the contents of a file. 27917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 28917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgulpublic final class Statistics { 29917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} data about each type of item */ 30917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final HashMap<String, Data> dataMap; 31917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 32917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 33917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance. 34917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 35917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public Statistics() { 36917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul dataMap = new HashMap<String, Data>(50); 37917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 38917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 39917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 40917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds the given item to the statistics. 41917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 42917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param item {@code non-null;} the item to add 43917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 44917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void add(Item item) { 45917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul String typeName = item.typeName(); 46917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Data data = dataMap.get(typeName); 47917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 48917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (data == null) { 49917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul dataMap.put(typeName, new Data(item, typeName)); 50917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 51917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul data.add(item); 52917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 53917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 54917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 55917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 56917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Adds the given list of items to the statistics. 57917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 58917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param list {@code non-null;} the list of items to add 59917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 60917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void addAll(Section list) { 61917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul Collection<? extends Item> items = list.items(); 62917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (Item item : items) { 63917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul add(item); 64917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 65917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 66917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 67917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 68917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writes the statistics as an annotation. 69917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 70917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 71917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 72917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public final void writeAnnotation(AnnotatedOutput out) { 73917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (dataMap.size() == 0) { 74917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return; 75917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 76917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 77917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.annotate(0, "\nstatistics:\n"); 78917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 79917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul TreeMap<String, Data> sortedData = new TreeMap<String, Data>(); 80917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 81917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (Data data : dataMap.values()) { 82917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sortedData.put(data.name, data); 83917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 84917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 85917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (Data data : sortedData.values()) { 86917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul data.writeAnnotation(out); 87917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 88917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 89917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 90917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String toHuman() { 91917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuilder sb = new StringBuilder(); 92917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 93917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append("Statistics:\n"); 94917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 95917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul TreeMap<String, Data> sortedData = new TreeMap<String, Data>(); 96917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 97917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (Data data : dataMap.values()) { 98917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sortedData.put(data.name, data); 99917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 100917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 101917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul for (Data data : sortedData.values()) { 102917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(data.toHuman()); 103917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 104917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 105917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 106917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 107917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 108917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 109917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Statistical data about a particular class. 110917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 111917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private static class Data { 112917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code non-null;} name to use as a label */ 113917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private final String name; 114917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 115917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0;} number of instances */ 116917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int count; 117917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 118917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0;} total size of instances in bytes */ 119917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int totalSize; 120917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 121917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0;} largest size of any individual item */ 122917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int largestSize; 123917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 124917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** {@code >= 0;} smallest size of any individual item */ 125917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul private int smallestSize; 126917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 127917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 128917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Constructs an instance for the given item. 129917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 130917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param item {@code non-null;} item in question 131917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param name {@code non-null;} type name to use 132917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 133917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public Data(Item item, String name) { 134917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int size = item.writeSize(); 135917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 136917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.name = name; 137917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.count = 1; 138917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.totalSize = size; 139917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.largestSize = size; 140917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul this.smallestSize = size; 141917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 142917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 143917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 144917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Incorporates a new item. This assumes the type name matches. 145917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 146917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param item {@code non-null;} item to incorporate 147917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 148917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void add(Item item) { 149917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int size = item.writeSize(); 150917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 151917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul count++; 152917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul totalSize += size; 153917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 154917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (size > largestSize) { 155917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul largestSize = size; 156917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 157917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 158917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (size < smallestSize) { 159917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul smallestSize = size; 160917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 161917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 162917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 163917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 164917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Writes this instance as an annotation. 165917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 166917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @param out {@code non-null;} where to write to 167917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 168917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public void writeAnnotation(AnnotatedOutput out) { 169917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul out.annotate(toHuman()); 170917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 171917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 172917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul /** 173917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * Generates a human-readable string for this data item. 174917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * 175917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul * @return string for human consumption. 176917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul */ 177917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul public String toHuman() { 178917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul StringBuilder sb = new StringBuilder(); 179917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 180917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" " + name + ": " + 181917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul count + " item" + (count == 1 ? "" : "s") + "; " + 182917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul totalSize + " bytes total\n"); 183917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 184917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul if (smallestSize == largestSize) { 185917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" " + smallestSize + " bytes/item\n"); 186917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } else { 187917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul int average = totalSize / count; 188917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul sb.append(" " + smallestSize + ".." + largestSize + 189917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul " bytes/item; average " + average + "\n"); 190917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 191917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul 192917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul return sb.toString(); 193917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 194917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul } 195917cb222329ee8c035c3ffaf947e4265761b9367Piotr Gurgul} 196